Skip to content

Commit 2e153a0

Browse files
Merge branch 'master' into feature/onetime-pad-cipher-6941
2 parents 609e75d + ac6fef1 commit 2e153a0

File tree

14 files changed

+556
-10
lines changed

14 files changed

+556
-10
lines changed

DIRECTORY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,7 @@
385385
- 📄 [Dinic](src/main/java/com/thealgorithms/graph/Dinic.java)
386386
- 📄 [Edmonds](src/main/java/com/thealgorithms/graph/Edmonds.java)
387387
- 📄 [EdmondsKarp](src/main/java/com/thealgorithms/graph/EdmondsKarp.java)
388+
- 📄 [GomoryHuTree](src/main/java/com/thealgorithms/graph/GomoryHuTree.java)
388389
- 📄 [HierholzerAlgorithm](src/main/java/com/thealgorithms/graph/HierholzerAlgorithm.java)
389390
- 📄 [HierholzerEulerianPath](src/main/java/com/thealgorithms/graph/HierholzerEulerianPath.java)
390391
- 📄 [HopcroftKarp](src/main/java/com/thealgorithms/graph/HopcroftKarp.java)

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,15 +119,15 @@
119119
<plugin>
120120
<groupId>com.github.spotbugs</groupId>
121121
<artifactId>spotbugs-maven-plugin</artifactId>
122-
<version>4.9.8.1</version>
122+
<version>4.9.8.2</version>
123123
<configuration>
124124
<excludeFilterFile>spotbugs-exclude.xml</excludeFilterFile>
125125
<includeTests>true</includeTests>
126126
<plugins>
127127
<plugin>
128128
<groupId>com.mebigfatguy.fb-contrib</groupId>
129129
<artifactId>fb-contrib</artifactId>
130-
<version>7.7.0</version>
130+
<version>7.7.1</version>
131131
</plugin>
132132
<plugin>
133133
<groupId>com.h3xstream.findsecbugs</groupId>

src/main/java/com/thealgorithms/backtracking/Combination.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@
77
import java.util.TreeSet;
88

99
/**
10-
* Finds all permutations of given array
11-
* @author Alan Piao (<a href="https://github.com/cpiao3">git-Alan Piao</a>)
10+
* Finds all combinations of a given array using backtracking algorithm * @author Alan Piao (<a href="https://github.com/cpiao3">git-Alan Piao</a>)
1211
*/
1312
public final class Combination {
1413
private Combination() {
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
package com.thealgorithms.graph;
2+
3+
import java.util.ArrayDeque;
4+
import java.util.Arrays;
5+
import java.util.Queue;
6+
7+
/**
8+
* Gomory–Hu tree construction for undirected graphs via n−1 max-flow computations.
9+
*
10+
* <p>API: {@code buildTree(int[][])} returns {@code {parent, weight}} arrays for the tree.
11+
*
12+
* @see <a href="https://en.wikipedia.org/wiki/Gomory%E2%80%93Hu_tree">Wikipedia: Gomory–Hu tree</a>
13+
*/
14+
15+
public final class GomoryHuTree {
16+
private GomoryHuTree() {
17+
}
18+
19+
public static int[][] buildTree(int[][] cap) {
20+
validateCapacityMatrix(cap);
21+
final int n = cap.length;
22+
if (n == 1) {
23+
return new int[][] {new int[] {-1}, new int[] {0}};
24+
}
25+
26+
int[] parent = new int[n];
27+
int[] weight = new int[n];
28+
Arrays.fill(parent, 0);
29+
parent[0] = -1;
30+
weight[0] = 0;
31+
32+
for (int s = 1; s < n; s++) {
33+
int t = parent[s];
34+
MaxFlowResult res = edmondsKarpWithMinCut(cap, s, t);
35+
int f = res.flow;
36+
weight[s] = f;
37+
38+
for (int v = 0; v < n; v++) {
39+
if (v != s && parent[v] == t && res.reachable[v]) {
40+
parent[v] = s;
41+
}
42+
}
43+
44+
if (t != 0 && res.reachable[parent[t]]) {
45+
parent[s] = parent[t];
46+
parent[t] = s;
47+
weight[s] = weight[t];
48+
weight[t] = f;
49+
}
50+
}
51+
return new int[][] {parent, weight};
52+
}
53+
54+
private static void validateCapacityMatrix(int[][] cap) {
55+
if (cap == null || cap.length == 0) {
56+
throw new IllegalArgumentException("Capacity matrix must not be null or empty");
57+
}
58+
final int n = cap.length;
59+
for (int i = 0; i < n; i++) {
60+
if (cap[i] == null || cap[i].length != n) {
61+
throw new IllegalArgumentException("Capacity matrix must be square");
62+
}
63+
for (int j = 0; j < n; j++) {
64+
if (cap[i][j] < 0) {
65+
throw new IllegalArgumentException("Capacities must be non-negative");
66+
}
67+
}
68+
}
69+
}
70+
71+
private static final class MaxFlowResult {
72+
final int flow;
73+
final boolean[] reachable;
74+
MaxFlowResult(int flow, boolean[] reachable) {
75+
this.flow = flow;
76+
this.reachable = reachable;
77+
}
78+
}
79+
80+
private static MaxFlowResult edmondsKarpWithMinCut(int[][] capacity, int source, int sink) {
81+
final int n = capacity.length;
82+
int[][] residual = new int[n][n];
83+
for (int i = 0; i < n; i++) {
84+
residual[i] = Arrays.copyOf(capacity[i], n);
85+
}
86+
87+
int[] parent = new int[n];
88+
int maxFlow = 0;
89+
90+
while (bfs(residual, source, sink, parent)) {
91+
int pathFlow = Integer.MAX_VALUE;
92+
for (int v = sink; v != source; v = parent[v]) {
93+
int u = parent[v];
94+
pathFlow = Math.min(pathFlow, residual[u][v]);
95+
}
96+
for (int v = sink; v != source; v = parent[v]) {
97+
int u = parent[v];
98+
residual[u][v] -= pathFlow;
99+
residual[v][u] += pathFlow;
100+
}
101+
maxFlow += pathFlow;
102+
}
103+
104+
boolean[] reachable = new boolean[n];
105+
markReachable(residual, source, reachable);
106+
return new MaxFlowResult(maxFlow, reachable);
107+
}
108+
109+
private static boolean bfs(int[][] residual, int source, int sink, int[] parent) {
110+
Arrays.fill(parent, -1);
111+
parent[source] = source;
112+
Queue<Integer> q = new ArrayDeque<>();
113+
q.add(source);
114+
while (!q.isEmpty()) {
115+
int u = q.poll();
116+
for (int v = 0; v < residual.length; v++) {
117+
if (residual[u][v] > 0 && parent[v] == -1) {
118+
parent[v] = u;
119+
if (v == sink) {
120+
return true;
121+
}
122+
q.add(v);
123+
}
124+
}
125+
}
126+
return false;
127+
}
128+
129+
private static void markReachable(int[][] residual, int source, boolean[] vis) {
130+
Arrays.fill(vis, false);
131+
Queue<Integer> q = new ArrayDeque<>();
132+
vis[source] = true;
133+
q.add(source);
134+
while (!q.isEmpty()) {
135+
int u = q.poll();
136+
for (int v = 0; v < residual.length; v++) {
137+
if (!vis[v] && residual[u][v] > 0) {
138+
vis[v] = true;
139+
q.add(v);
140+
}
141+
}
142+
}
143+
}
144+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.thealgorithms.maths;
2+
3+
/**
4+
* In number theory, an abundant number or excessive number is a positive integer for which
5+
* the sum of its proper divisors is greater than the number.
6+
* Equivalently, it is a number for which the sum of proper divisors (or aliquot sum) is greater than n.
7+
*
8+
* The integer 12 is the first abundant number. Its proper divisors are 1, 2, 3, 4 and 6 for a total of 16.
9+
*
10+
* Wiki: https://en.wikipedia.org/wiki/Abundant_number
11+
*/
12+
public final class AbundantNumber {
13+
14+
private AbundantNumber() {
15+
}
16+
17+
// Function to calculate sum of all divisors including n
18+
private static int sumOfDivisors(int n) {
19+
int sum = 1 + n; // 1 and n are always divisors
20+
for (int i = 2; i <= n / 2; i++) {
21+
if (n % i == 0) {
22+
sum += i; // adding divisor to sum
23+
}
24+
}
25+
return sum;
26+
}
27+
28+
// Common validation method
29+
private static void validatePositiveNumber(int number) {
30+
if (number <= 0) {
31+
throw new IllegalArgumentException("Number must be positive.");
32+
}
33+
}
34+
35+
/**
36+
* Check if {@code number} is an Abundant number or not by checking sum of divisors > 2n
37+
*
38+
* @param number the number
39+
* @return {@code true} if {@code number} is an Abundant number, otherwise false
40+
*/
41+
public static boolean isAbundant(int number) {
42+
validatePositiveNumber(number);
43+
44+
return sumOfDivisors(number) > 2 * number;
45+
}
46+
47+
/**
48+
* Check if {@code number} is an Abundant number or not by checking Aliquot Sum > n
49+
*
50+
* @param number the number
51+
* @return {@code true} if {@code number} is a Abundant number, otherwise false
52+
*/
53+
public static boolean isAbundantNumber(int number) {
54+
validatePositiveNumber(number);
55+
56+
return AliquotSum.getAliquotSum(number) > number;
57+
}
58+
}

src/main/java/com/thealgorithms/maths/Area.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ public static double surfaceAreaCylinder(final double radius, final double heigh
9696
throw new IllegalArgumentException(POSITIVE_RADIUS);
9797
}
9898
if (height <= 0) {
99-
throw new IllegalArgumentException(POSITIVE_RADIUS);
99+
throw new IllegalArgumentException(POSITIVE_HEIGHT);
100100
}
101101
return 2 * (Math.PI * radius * radius + Math.PI * radius * height);
102102
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.thealgorithms.maths;
2+
3+
/**
4+
* In number theory, an evil number is a non-negative integer that has an even number of 1s in its binary expansion.
5+
* Non-negative integers that are not evil are called odious numbers.
6+
*
7+
* Evil Number Wiki: https://en.wikipedia.org/wiki/Evil_number
8+
* Odious Number Wiki: https://en.wikipedia.org/wiki/Odious_number
9+
*/
10+
public final class EvilNumber {
11+
12+
private EvilNumber() {
13+
}
14+
15+
// Function to count number of one bits in a number using bitwise operators
16+
private static int countOneBits(int number) {
17+
int oneBitCounter = 0;
18+
while (number > 0) {
19+
oneBitCounter += number & 1; // increment count if last bit is 1
20+
number >>= 1; // right shift to next bit
21+
}
22+
return oneBitCounter;
23+
}
24+
25+
/**
26+
* Check either {@code number} is an Evil number or Odious number
27+
*
28+
* @param number the number
29+
* @return {@code true} if {@code number} is an Evil number, otherwise false (in case of of Odious number)
30+
*/
31+
public static boolean isEvilNumber(int number) {
32+
if (number < 0) {
33+
throw new IllegalArgumentException("Negative numbers are not allowed.");
34+
}
35+
36+
int noOfOneBits = countOneBits(number);
37+
return noOfOneBits % 2 == 0;
38+
}
39+
}

src/main/java/com/thealgorithms/maths/Perimeter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public static float perimeterRegularPolygon(int n, float side) {
2727
* @param side2 for length of side 2
2828
* @param side3 for length of side 3
2929
* @param sides for length of remaining sides
30-
* @return Perimeter of given trapezoid.
30+
* @return Perimeter of given irregular polygon.
3131
*/
3232
public static float perimeterIrregularPolygon(float side1, float side2, float side3, float... sides) {
3333
float perimeter = side1 + side2 + side3;

src/main/java/com/thealgorithms/randomized/MonteCarloIntegration.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,21 @@ private static double doApproximate(Function<Double, Double> fx, double a, doubl
6464
if (!validate(fx, a, b, n)) {
6565
throw new IllegalArgumentException("Invalid input parameters");
6666
}
67-
double totalArea = 0.0;
67+
double total = 0.0;
6868
double interval = b - a;
69-
for (int i = 0; i < n; i++) {
69+
int pairs = n / 2;
70+
for (int i = 0; i < pairs; i++) {
71+
double u = generator.nextDouble();
72+
double x1 = a + u * interval;
73+
double x2 = a + (1.0 - u) * interval;
74+
total += fx.apply(x1);
75+
total += fx.apply(x2);
76+
}
77+
if ((n & 1) == 1) {
7078
double x = a + generator.nextDouble() * interval;
71-
totalArea += fx.apply(x);
79+
total += fx.apply(x);
7280
}
73-
return interval * totalArea / n;
81+
return interval * total / n;
7482
}
7583

7684
private static boolean validate(Function<Double, Double> fx, double a, double b, int n) {
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package com.thealgorithms.stacks;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
import java.util.Stack;
6+
7+
/**
8+
* Valid Parentheses Problem
9+
*
10+
* Given a string containing just the characters '(', ')', '{', '}', '[' and ']',
11+
* determine if the input string is valid.
12+
*
13+
* An input string is valid if:
14+
* 1. Open brackets must be closed by the same type of brackets.
15+
* 2. Open brackets must be closed in the correct order.
16+
* 3. Every close bracket has a corresponding open bracket of the same type.
17+
*
18+
* Examples:
19+
* Input: "()"
20+
* Output: true
21+
*
22+
* Input: "()[]{}"
23+
* Output: true
24+
*
25+
* Input: "(]"
26+
* Output: false
27+
*
28+
* Input: "([)]"
29+
* Output: false
30+
*
31+
* @author Gokul45-45
32+
*/
33+
public final class ValidParentheses {
34+
private ValidParentheses() {
35+
}
36+
37+
/**
38+
* Checks if the given string has valid parentheses
39+
*
40+
* @param s the input string containing parentheses
41+
* @return true if valid, false otherwise
42+
*/
43+
public static boolean isValid(String s) {
44+
if (s == null || s.length() % 2 != 0) {
45+
return false;
46+
}
47+
48+
Map<Character, Character> parenthesesMap = new HashMap<>();
49+
parenthesesMap.put('(', ')');
50+
parenthesesMap.put('{', '}');
51+
parenthesesMap.put('[', ']');
52+
53+
Stack<Character> stack = new Stack<>();
54+
55+
for (char c : s.toCharArray()) {
56+
if (parenthesesMap.containsKey(c)) {
57+
// Opening bracket - push to stack
58+
stack.push(c);
59+
} else {
60+
// Closing bracket - check if it matches
61+
if (stack.isEmpty()) {
62+
return false;
63+
}
64+
char openBracket = stack.pop();
65+
if (parenthesesMap.get(openBracket) != c) {
66+
return false;
67+
}
68+
}
69+
}
70+
71+
// Stack should be empty if all brackets are matched
72+
return stack.isEmpty();
73+
}
74+
}

0 commit comments

Comments
 (0)