Skip to content

Commit 5d7703c

Browse files
Merge branch 'master' into optimal-binary-search-tree
2 parents 04c7665 + 9729e56 commit 5d7703c

24 files changed

+1000
-98
lines changed

.github/workflows/build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,15 @@ jobs:
2020
if: >-
2121
github.event_name == 'pull_request' &&
2222
github.event.pull_request.head.repo.full_name != github.repository
23-
uses: codecov/codecov-action@v5
23+
uses: codecov/codecov-action@v6
2424
with:
2525
fail_ci_if_error: true
2626
- name: Upload coverage to codecov (with token)
2727
if: >
2828
github.repository == 'TheAlgorithms/Java' &&
2929
(github.event_name != 'pull_request' ||
3030
github.event.pull_request.head.repo.full_name == github.repository)
31-
uses: codecov/codecov-action@v5
31+
uses: codecov/codecov-action@v6
3232
with:
3333
token: ${{ secrets.CODECOV_TOKEN }}
3434
fail_ci_if_error: true

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,14 +112,14 @@
112112
<dependency>
113113
<groupId>com.puppycrawl.tools</groupId>
114114
<artifactId>checkstyle</artifactId>
115-
<version>13.3.0</version>
115+
<version>13.4.0</version>
116116
</dependency>
117117
</dependencies>
118118
</plugin>
119119
<plugin>
120120
<groupId>com.github.spotbugs</groupId>
121121
<artifactId>spotbugs-maven-plugin</artifactId>
122-
<version>4.9.8.2</version>
122+
<version>4.9.8.3</version>
123123
<configuration>
124124
<excludeFilterFile>spotbugs-exclude.xml</excludeFilterFile>
125125
<includeTests>true</includeTests>

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

Lines changed: 25 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -35,51 +35,34 @@
3535
* - Stack space for the recursive DFS function, where L is the maximum depth of recursion (length of the word).
3636
*/
3737
public class WordSearch {
38-
private final int[] dx = {0, 0, 1, -1};
39-
private final int[] dy = {1, -1, 0, 0};
40-
private boolean[][] visited;
41-
private char[][] board;
42-
private String word;
43-
44-
/**
45-
* Checks if the given (x, y) coordinates are valid positions in the board.
46-
*
47-
* @param x The row index.
48-
* @param y The column index.
49-
* @return True if the coordinates are within the bounds of the board; false otherwise.
50-
*/
51-
private boolean isValid(int x, int y) {
52-
return x >= 0 && x < board.length && y >= 0 && y < board[0].length;
53-
}
5438

5539
/**
5640
* Performs Depth First Search (DFS) from the cell (x, y)
5741
* to search for the next character in the word.
5842
*
5943
* @param x The current row index.
6044
* @param y The current column index.
61-
* @param nextIdx The index of the next character in the word to be matched.
45+
* @param idx The index of the next character in the word to be matched.
6246
* @return True if a valid path is found to match the remaining characters of the word; false otherwise.
6347
*/
64-
private boolean doDFS(int x, int y, int nextIdx) {
65-
visited[x][y] = true;
66-
if (nextIdx == word.length()) {
48+
49+
private boolean dfs(char[][] board, int x, int y, String word, int idx) {
50+
if (idx == word.length()) {
6751
return true;
6852
}
6953

70-
for (int i = 0; i < 4; ++i) {
71-
int xi = x + dx[i];
72-
int yi = y + dy[i];
73-
if (isValid(xi, yi) && board[xi][yi] == word.charAt(nextIdx) && !visited[xi][yi]) {
74-
boolean exists = doDFS(xi, yi, nextIdx + 1);
75-
if (exists) {
76-
return true;
77-
}
78-
}
54+
if (x < 0 || y < 0 || x >= board.length || y >= board[0].length || board[x][y] != word.charAt(idx)) {
55+
return false;
7956
}
8057

81-
visited[x][y] = false; // Backtrack
82-
return false;
58+
char temp = board[x][y];
59+
board[x][y] = '#';
60+
61+
boolean found = dfs(board, x + 1, y, word, idx + 1) || dfs(board, x - 1, y, word, idx + 1) || dfs(board, x, y + 1, word, idx + 1) || dfs(board, x, y - 1, word, idx + 1);
62+
63+
board[x][y] = temp;
64+
65+
return found;
8366
}
8467

8568
/**
@@ -90,20 +73,21 @@ private boolean doDFS(int x, int y, int nextIdx) {
9073
* @param word The target word to search for in the board.
9174
* @return True if the word exists in the board; false otherwise.
9275
*/
76+
9377
public boolean exist(char[][] board, String word) {
94-
this.board = board;
95-
this.word = word;
96-
for (int i = 0; i < board.length; ++i) {
97-
for (int j = 0; j < board[0].length; ++j) {
98-
if (board[i][j] == word.charAt(0)) {
99-
visited = new boolean[board.length][board[0].length];
100-
boolean exists = doDFS(i, j, 1);
101-
if (exists) {
102-
return true;
103-
}
78+
79+
int m = board.length;
80+
int n = board[0].length;
81+
82+
// DFS search
83+
for (int i = 0; i < m; i++) {
84+
for (int j = 0; j < n; j++) {
85+
if (board[i][j] == word.charAt(0) && dfs(board, i, j, word, 0)) {
86+
return true;
10487
}
10588
}
10689
}
90+
10791
return false;
10892
}
10993
}
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package com.thealgorithms.graph;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
/**
7+
* Implementation of Tarjan's Bridge-Finding Algorithm for undirected graphs.
8+
*
9+
* <p>A <b>bridge</b> (also called a cut-edge) is an edge in an undirected graph whose removal
10+
* increases the number of connected components. Bridges represent critical links
11+
* in a network — if any bridge is removed, part of the network becomes unreachable.</p>
12+
*
13+
* <p>The algorithm performs a single Depth-First Search (DFS) traversal, tracking two
14+
* values for each vertex:</p>
15+
* <ul>
16+
* <li><b>discoveryTime</b> — the time step at which the vertex was first visited.</li>
17+
* <li><b>lowLink</b> — the smallest discovery time reachable from the subtree rooted
18+
* at that vertex (via back edges).</li>
19+
* </ul>
20+
*
21+
* <p>An edge (u, v) is a bridge if and only if {@code lowLink[v] > discoveryTime[u]},
22+
* meaning there is no back edge from the subtree of v that can reach u or any ancestor of u.</p>
23+
*
24+
* <p>Time Complexity: O(V + E), where V is the number of vertices and E is the number of edges.</p>
25+
* <p>Space Complexity: O(V + E) for the adjacency list, discovery/low arrays, and recursion stack.</p>
26+
*
27+
* @see <a href="https://en.wikipedia.org/wiki/Bridge_(graph_theory)">Wikipedia: Bridge (graph theory)</a>
28+
*/
29+
public final class TarjanBridges {
30+
31+
private TarjanBridges() {
32+
throw new UnsupportedOperationException("Utility class");
33+
}
34+
35+
/**
36+
* Finds all bridge edges in an undirected graph.
37+
*
38+
* <p>The graph is represented as an adjacency list where each vertex is identified by
39+
* an integer in the range {@code [0, vertexCount)}. For each undirected edge (u, v),
40+
* v must appear in {@code adjacencyList.get(u)} and u must appear in
41+
* {@code adjacencyList.get(v)}.</p>
42+
*
43+
* @param vertexCount the total number of vertices in the graph (must be non-negative)
44+
* @param adjacencyList the adjacency list representation of the graph; must contain
45+
* exactly {@code vertexCount} entries (one per vertex)
46+
* @return a list of bridge edges, where each bridge is represented as an {@code int[]}
47+
* of length 2 with {@code edge[0] < edge[1]}; returns an empty list if no bridges exist
48+
* @throws IllegalArgumentException if {@code vertexCount} is negative, or if
49+
* {@code adjacencyList} is null or its size does not match
50+
* {@code vertexCount}
51+
*/
52+
public static List<int[]> findBridges(int vertexCount, List<List<Integer>> adjacencyList) {
53+
if (vertexCount < 0) {
54+
throw new IllegalArgumentException("vertexCount must be non-negative");
55+
}
56+
if (adjacencyList == null || adjacencyList.size() != vertexCount) {
57+
throw new IllegalArgumentException("adjacencyList size must equal vertexCount");
58+
}
59+
60+
List<int[]> bridges = new ArrayList<>();
61+
62+
if (vertexCount == 0) {
63+
return bridges;
64+
}
65+
66+
BridgeFinder finder = new BridgeFinder(vertexCount, adjacencyList, bridges);
67+
68+
// Run DFS from every unvisited vertex to handle disconnected graphs
69+
for (int i = 0; i < vertexCount; i++) {
70+
if (!finder.visited[i]) {
71+
finder.dfs(i, -1);
72+
}
73+
}
74+
75+
return bridges;
76+
}
77+
78+
private static class BridgeFinder {
79+
private final List<List<Integer>> adjacencyList;
80+
private final List<int[]> bridges;
81+
private final int[] discoveryTime;
82+
private final int[] lowLink;
83+
boolean[] visited;
84+
private int timer;
85+
86+
BridgeFinder(int vertexCount, List<List<Integer>> adjacencyList, List<int[]> bridges) {
87+
this.adjacencyList = adjacencyList;
88+
this.bridges = bridges;
89+
this.discoveryTime = new int[vertexCount];
90+
this.lowLink = new int[vertexCount];
91+
this.visited = new boolean[vertexCount];
92+
this.timer = 0;
93+
}
94+
95+
/**
96+
* Performs DFS from the given vertex, computing discovery times and low-link values,
97+
* and collects any bridge edges found.
98+
*
99+
* @param u the current vertex being explored
100+
* @param parent the parent of u in the DFS tree (-1 if u is a root)
101+
*/
102+
void dfs(int u, int parent) {
103+
visited[u] = true;
104+
discoveryTime[u] = timer;
105+
lowLink[u] = timer;
106+
timer++;
107+
108+
for (int v : adjacencyList.get(u)) {
109+
if (!visited[v]) {
110+
dfs(v, u);
111+
lowLink[u] = Math.min(lowLink[u], lowLink[v]);
112+
113+
if (lowLink[v] > discoveryTime[u]) {
114+
bridges.add(new int[] {Math.min(u, v), Math.max(u, v)});
115+
}
116+
} else if (v != parent) {
117+
lowLink[u] = Math.min(lowLink[u], discoveryTime[v]);
118+
}
119+
}
120+
}
121+
}
122+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package com.thealgorithms.maths;
2+
3+
/**
4+
* Class for correlation of two discrete variables
5+
*/
6+
7+
public final class Correlation {
8+
private Correlation() {
9+
}
10+
11+
public static final double DELTA = 1e-9;
12+
13+
/**
14+
* Discrete correlation function.
15+
* Correlation between two discrete variables is calculated
16+
* according to the formula: Cor(x, y)=Cov(x, y)/sqrt(Var(x)*Var(y)).
17+
* Correlation with a constant variable is taken to be zero.
18+
*
19+
* @param x The first discrete variable
20+
* @param y The second discrete variable
21+
* @param n The number of values for each variable
22+
* @return The result of the correlation of variables x,y.
23+
*/
24+
public static double correlation(double[] x, double[] y, int n) {
25+
double exy = 0; // E(XY)
26+
double ex = 0; // E(X)
27+
double exx = 0; // E(X^2)
28+
double ey = 0; // E(Y)
29+
double eyy = 0; // E(Y^2)
30+
for (int i = 0; i < n; i++) {
31+
exy += x[i] * y[i];
32+
ex += x[i];
33+
exx += x[i] * x[i];
34+
ey += y[i];
35+
eyy += y[i] * y[i];
36+
}
37+
exy /= n;
38+
ex /= n;
39+
exx /= n;
40+
ey /= n;
41+
eyy /= n;
42+
double cov = exy - ex * ey; // Cov(X, Y) = E(XY)-E(X)E(Y)
43+
double varx = Math.sqrt(exx - ex * ex); // Var(X) = sqrt(E(X^2)-E(X)^2)
44+
double vary = Math.sqrt(eyy - ey * ey); // Var(Y) = sqrt(E(Y^2)-E(Y)^2)
45+
if (varx * vary < DELTA) { // Var(X) = 0 means X = const, the same about Y
46+
return 0;
47+
} else {
48+
return cov / Math.sqrt(varx * vary);
49+
}
50+
}
51+
}
Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,19 @@
11
package com.thealgorithms.maths;
22

3+
import java.math.BigInteger;
4+
35
public final class Factorial {
46
private Factorial() {
57
}
68

7-
/**
8-
* Calculate factorial N using iteration
9-
*
10-
* @param n the number
11-
* @return the factorial of {@code n}
12-
*/
13-
public static long factorial(int n) {
9+
public static BigInteger factorial(int n) {
1410
if (n < 0) {
1511
throw new IllegalArgumentException("Input number cannot be negative");
1612
}
17-
long factorial = 1;
18-
for (int i = 1; i <= n; ++i) {
19-
factorial *= i;
13+
BigInteger result = BigInteger.ONE;
14+
for (int i = 1; i <= n; i++) {
15+
result = result.multiply(BigInteger.valueOf(i));
2016
}
21-
return factorial;
17+
return result;
2218
}
2319
}

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,28 @@ public static Double harmonic(final Iterable<Double> numbers) {
107107
return size / sumOfReciprocals;
108108
}
109109

110+
/**
111+
* Computes the quadratic mean (root mean square) of the given numbers.
112+
* <p>
113+
* The quadratic mean is calculated as: √[(x₁^2 × x₂^2 × ... × xₙ^2)/n]
114+
* </p>
115+
* <p>
116+
* Example: For numbers [1, 7], the quadratic mean is √[(1^2+7^2)/2] = √25 = 5.0
117+
* </p>
118+
*
119+
* @param numbers the input numbers (must not be empty)
120+
* @return the quadratic mean of the input numbers
121+
* @throws IllegalArgumentException if the input is empty
122+
* @see <a href="https://en.wikipedia.org/wiki/Root_mean_square">Quadratic
123+
* Mean</a>
124+
*/
125+
public static Double quadratic(final Iterable<Double> numbers) {
126+
checkIfNotEmpty(numbers);
127+
double sumOfSquares = StreamSupport.stream(numbers.spliterator(), false).reduce(0d, (x, y) -> x + y * y);
128+
int size = IterableUtils.size(numbers);
129+
return Math.pow(sumOfSquares / size, 0.5);
130+
}
131+
110132
/**
111133
* Validates that the input iterable is not empty.
112134
*

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,4 +125,16 @@ public static double volumeFrustumOfPyramid(double upperBaseArea, double lowerBa
125125
public static double volumeTorus(double majorRadius, double minorRadius) {
126126
return 2 * Math.PI * Math.PI * majorRadius * minorRadius * minorRadius;
127127
}
128+
129+
/**
130+
* Calculate the volume of an ellipsoid.
131+
*
132+
* @param a first semi-axis of an ellipsoid
133+
* @param b second semi-axis of an ellipsoid
134+
* @param c third semi-axis of an ellipsoid
135+
* @return volume of the ellipsoid
136+
*/
137+
public static double volumeEllipsoid(double a, double b, double c) {
138+
return (4 * Math.PI * a * b * c) / 3;
139+
}
128140
}

src/main/java/com/thealgorithms/physics/ElasticCollision2D.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public static void resolveCollision(Body a, Body b) {
4141
double dy = b.y - a.y;
4242
double dist = Math.hypot(dx, dy);
4343

44-
if (dist == 0) {
44+
if (dist < a.radius + b.radius) {
4545
return; // overlapping
4646
}
4747

0 commit comments

Comments
 (0)