Skip to content

Commit 228aa08

Browse files
Merge branch 'master' into master
2 parents e6df7dd + 48e02b3 commit 228aa08

File tree

15 files changed

+575
-23
lines changed

15 files changed

+575
-23
lines changed

.github/workflows/infer.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333

3434
- name: Cache infer build
3535
id: cache-infer
36-
uses: actions/cache@v4
36+
uses: actions/cache@v5
3737
with:
3838
path: infer
3939
key: ${{ runner.os }}-infer-${{ env.year_week }}

DIRECTORY.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,7 @@
822822
- 📄 [Upper](src/main/java/com/thealgorithms/strings/Upper.java)
823823
- 📄 [ValidParentheses](src/main/java/com/thealgorithms/strings/ValidParentheses.java)
824824
- 📄 [WordLadder](src/main/java/com/thealgorithms/strings/WordLadder.java)
825+
- 📄 [ZAlgorithm](src/main/java/com/thealgorithms/strings/ZAlgorithm.java)
825826
- 📁 **zigZagPattern**
826827
- 📄 [ZigZagPattern](src/main/java/com/thealgorithms/strings/zigZagPattern/ZigZagPattern.java)
827828
- 📁 **tree**
@@ -1579,6 +1580,7 @@
15791580
- 📄 [UpperTest](src/test/java/com/thealgorithms/strings/UpperTest.java)
15801581
- 📄 [ValidParenthesesTest](src/test/java/com/thealgorithms/strings/ValidParenthesesTest.java)
15811582
- 📄 [WordLadderTest](src/test/java/com/thealgorithms/strings/WordLadderTest.java)
1583+
- 📄 [ZAlgorithmTest](src/test/java/com/thealgorithms/strings/ZAlgorithmTest.java)
15821584
- 📁 **zigZagPattern**
15831585
- 📄 [ZigZagPatternTest](src/test/java/com/thealgorithms/strings/zigZagPattern/ZigZagPatternTest.java)
15841586
- 📁 **tree**

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@
112112
<dependency>
113113
<groupId>com.puppycrawl.tools</groupId>
114114
<artifactId>checkstyle</artifactId>
115-
<version>12.2.0</version>
115+
<version>12.3.0</version>
116116
</dependency>
117117
</dependencies>
118118
</plugin>
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package com.thealgorithms.datastructures.trees;
2+
3+
/**
4+
* Leetcode 606: Construct String from Binary Tree:
5+
* https://leetcode.com/problems/construct-string-from-binary-tree/
6+
*
7+
* Utility class to convert a {@link BinaryTree} into its string representation.
8+
* <p>
9+
* The conversion follows a preorder traversal pattern (root → left → right)
10+
* and uses parentheses to denote the tree structure.
11+
* Empty parentheses "()" are used to explicitly represent missing left children
12+
* when a right child exists, ensuring the structure is unambiguous.
13+
* </p>
14+
*
15+
* <h2>Rules:</h2>
16+
* <ul>
17+
* <li>Each node is represented as {@code (value)}.</li>
18+
* <li>If a node has only a right child, include {@code ()} before the right
19+
* child
20+
* to indicate the missing left child.</li>
21+
* <li>If a node has no children, it appears as just {@code (value)}.</li>
22+
* <li>The outermost parentheses are removed from the final string.</li>
23+
* </ul>
24+
*
25+
* <h3>Example:</h3>
26+
*
27+
* <pre>
28+
* Input tree:
29+
* 1
30+
* / \
31+
* 2 3
32+
* \
33+
* 4
34+
*
35+
* Output string:
36+
* "1(2()(4))(3)"
37+
* </pre>
38+
*
39+
* <p>
40+
* This implementation matches the logic from LeetCode problem 606:
41+
* <i>Construct String from Binary Tree</i>.
42+
* </p>
43+
*
44+
* @author Muhammad Junaid
45+
* @see BinaryTree
46+
*/
47+
public class BinaryTreeToString {
48+
49+
/** String builder used to accumulate the string representation. */
50+
private StringBuilder sb;
51+
52+
/**
53+
* Converts a binary tree (given its root node) to its string representation.
54+
*
55+
* @param root the root node of the binary tree
56+
* @return the string representation of the binary tree, or an empty string if
57+
* the tree is null
58+
*/
59+
public String tree2str(BinaryTree.Node root) {
60+
if (root == null) {
61+
return "";
62+
}
63+
64+
sb = new StringBuilder();
65+
dfs(root);
66+
67+
// Remove the leading and trailing parentheses added by the root call
68+
return sb.substring(1, sb.length() - 1);
69+
}
70+
71+
/**
72+
* Performs a recursive depth-first traversal to build the string.
73+
* Each recursive call appends the node value and its children (if any)
74+
* enclosed in parentheses.
75+
*
76+
* @param node the current node being processed
77+
*/
78+
private void dfs(BinaryTree.Node node) {
79+
if (node == null) {
80+
return;
81+
}
82+
83+
sb.append("(").append(node.data);
84+
85+
// Recursively build left and right subtrees
86+
if (node.left != null) {
87+
dfs(node.left);
88+
}
89+
90+
// Handle the special case: right child exists but left child is null
91+
if (node.right != null && node.left == null) {
92+
sb.append("()");
93+
dfs(node.right);
94+
} else if (node.right != null) {
95+
dfs(node.right);
96+
}
97+
98+
sb.append(")");
99+
}
100+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.thealgorithms.maths;
2+
3+
/**
4+
* In mathematics, the extended Euclidean algorithm is an extension to the
5+
* Euclidean algorithm, and computes, in addition to the greatest common divisor
6+
* (gcd) of integers a and b, also the coefficients of Bézout's identity, which
7+
* are integers x and y such that ax + by = gcd(a, b).
8+
*
9+
* <p>
10+
* For more details, see
11+
* https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm
12+
*/
13+
public final class ExtendedEuclideanAlgorithm {
14+
15+
private ExtendedEuclideanAlgorithm() {
16+
}
17+
18+
/**
19+
* This method implements the extended Euclidean algorithm.
20+
*
21+
* @param a The first number.
22+
* @param b The second number.
23+
* @return An array of three integers:
24+
* <ul>
25+
* <li>Index 0: The greatest common divisor (gcd) of a and b.</li>
26+
* <li>Index 1: The value of x in the equation ax + by = gcd(a, b).</li>
27+
* <li>Index 2: The value of y in the equation ax + by = gcd(a, b).</li>
28+
* </ul>
29+
*/
30+
public static long[] extendedGCD(long a, long b) {
31+
if (b == 0) {
32+
// Base case: gcd(a, 0) = a. The equation is a*1 + 0*0 = a.
33+
return new long[] {a, 1, 0};
34+
}
35+
36+
// Recursive call
37+
long[] result = extendedGCD(b, a % b);
38+
long gcd = result[0];
39+
long x1 = result[1];
40+
long y1 = result[2];
41+
42+
// Update coefficients using the results from the recursive call
43+
long x = y1;
44+
long y = x1 - a / b * y1;
45+
46+
return new long[] {gcd, x, y};
47+
}
48+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package com.thealgorithms.maths;
2+
3+
/**
4+
* In number theory, a lucky number is a natural number in a set which is generated by a certain "sieve".
5+
* This sieve is similar to the sieve of Eratosthenes that generates the primes,
6+
* but it eliminates numbers based on their position in the remaining set,
7+
* instead of their value (or position in the initial set of natural numbers).
8+
*
9+
* Wiki: https://en.wikipedia.org/wiki/Lucky_number
10+
*/
11+
public final class LuckyNumber {
12+
13+
private LuckyNumber() {
14+
}
15+
16+
// Common validation method
17+
private static void validatePositiveNumber(int number) {
18+
if (number <= 0) {
19+
throw new IllegalArgumentException("Number must be positive.");
20+
}
21+
}
22+
23+
// Function to check recursively for Lucky Number
24+
private static boolean isLuckyRecursiveApproach(int n, int counter) {
25+
// Base case: If counter exceeds n, number is lucky
26+
if (counter > n) {
27+
return true;
28+
}
29+
30+
// If number is eliminated in this step, it's not lucky
31+
if (n % counter == 0) {
32+
return false;
33+
}
34+
35+
// Calculate new position after removing every counter-th number
36+
int newNumber = n - (n / counter);
37+
38+
// Recursive call for next round
39+
return isLuckyRecursiveApproach(newNumber, counter + 1);
40+
}
41+
42+
/**
43+
* Check if {@code number} is a Lucky number or not using recursive approach
44+
*
45+
* @param number the number
46+
* @return {@code true} if {@code number} is a Lucky number, otherwise false
47+
*/
48+
public static boolean isLuckyNumber(int number) {
49+
validatePositiveNumber(number);
50+
int counterStarting = 2;
51+
return isLuckyRecursiveApproach(number, counterStarting);
52+
}
53+
54+
/**
55+
* Check if {@code number} is a Lucky number or not using iterative approach
56+
*
57+
* @param number the number
58+
* @return {@code true} if {@code number} is a Lucky number, otherwise false
59+
*/
60+
public static boolean isLucky(int number) {
61+
validatePositiveNumber(number);
62+
63+
int counter = 2; // Position starts from 2 (since first elimination happens at 2)
64+
int position = number; // The position of the number in the sequence
65+
66+
while (counter <= position) {
67+
if (position % counter == 0) {
68+
return false;
69+
} // Number is eliminated
70+
71+
// Update the position of n after removing every counter-th number
72+
position = position - (position / counter);
73+
counter++;
74+
}
75+
76+
return true; // Survives all eliminations → Lucky Number
77+
}
78+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package com.thealgorithms.physics;
2+
3+
/**
4+
* Implements the Thin Lens Formula used in ray optics:
5+
*
6+
* <pre>
7+
* 1/f = 1/v + 1/u
8+
* </pre>
9+
*
10+
* where:
11+
* <ul>
12+
* <li>f = focal length</li>
13+
* <li>u = object distance</li>
14+
* <li>v = image distance</li>
15+
* </ul>
16+
*
17+
* Uses the Cartesian sign convention.
18+
*
19+
* @see <a href="https://en.wikipedia.org/wiki/Thin_lens">Thin Lens</a>
20+
*/
21+
public final class ThinLens {
22+
23+
private ThinLens() {
24+
throw new AssertionError("No instances.");
25+
}
26+
27+
/**
28+
* Computes the image distance using the thin lens formula.
29+
*
30+
* @param focalLength focal length of the lens (f)
31+
* @param objectDistance object distance (u)
32+
* @return image distance (v)
33+
* @throws IllegalArgumentException if focal length or object distance is zero
34+
*/
35+
public static double imageDistance(double focalLength, double objectDistance) {
36+
37+
if (focalLength == 0 || objectDistance == 0) {
38+
throw new IllegalArgumentException("Focal length and object distance must be non-zero.");
39+
}
40+
41+
return 1.0 / ((1.0 / focalLength) - (1.0 / objectDistance));
42+
}
43+
44+
/**
45+
* Computes magnification of the image.
46+
*
47+
* <pre>
48+
* m = v / u
49+
* </pre>
50+
*
51+
* @param imageDistance image distance (v)
52+
* @param objectDistance object distance (u)
53+
* @return magnification
54+
* @throws IllegalArgumentException if object distance is zero
55+
*/
56+
public static double magnification(double imageDistance, double objectDistance) {
57+
58+
if (objectDistance == 0) {
59+
throw new IllegalArgumentException("Object distance must be non-zero.");
60+
}
61+
62+
return imageDistance / objectDistance;
63+
}
64+
65+
/**
66+
* Determines whether the image formed is real or virtual.
67+
*
68+
* @param imageDistance image distance (v)
69+
* @return {@code true} if image is real, {@code false} if virtual
70+
*/
71+
public static boolean isRealImage(double imageDistance) {
72+
return imageDistance > 0;
73+
}
74+
}

src/main/java/com/thealgorithms/recursion/FibonacciSeries.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ private FibonacciSeries() {
1212
throw new UnsupportedOperationException("Utility class");
1313
}
1414
public static int fibonacci(int n) {
15+
if (n < 0) {
16+
throw new IllegalArgumentException("n must be a non-negative integer");
17+
}
1518
if (n <= 1) {
1619
return n;
17-
} else {
18-
return fibonacci(n - 1) + fibonacci(n - 2);
1920
}
21+
return fibonacci(n - 1) + fibonacci(n - 2);
2022
}
2123
}

0 commit comments

Comments
 (0)