Skip to content

Commit 4447b5e

Browse files
authored
Merge branch 'master' into vardhan30016-patch-2
2 parents 488efa2 + c06c0f0 commit 4447b5e

File tree

55 files changed

+2794
-90
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+2794
-90
lines changed

.github/pull_request_template.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ In order to reduce the number of notifications sent to the maintainers, please:
1313
- [ ] All filenames are in PascalCase.
1414
- [ ] All functions and variable names follow Java naming conventions.
1515
- [ ] All new algorithms have a URL in their comments that points to Wikipedia or other similar explanations.
16-
- [ ] All new code is formatted with `clang-format -i --style=file path/to/your/file.java`
16+
- [ ] All new algorithms include a corresponding test class that validates their functionality.
17+
- [ ] All new code is formatted with `clang-format -i --style=file path/to/your/file.java`

.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 }}

.gitpod.dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM gitpod/workspace-java-21:2025-10-06-13-14-25
1+
FROM gitpod/workspace-java-21:2025-11-14-10-05-32
22

33
ENV LLVM_SCRIPT="tmp_llvm.sh"
44

DIRECTORY.md

Lines changed: 36 additions & 2 deletions
Large diffs are not rendered by default.

pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
<dependency>
4343
<groupId>org.mockito</groupId>
4444
<artifactId>mockito-core</artifactId>
45-
<version>5.20.0</version>
45+
<version>5.21.0</version>
4646
<scope>test</scope>
4747
</dependency>
4848
<dependency>
@@ -112,7 +112,7 @@
112112
<dependency>
113113
<groupId>com.puppycrawl.tools</groupId>
114114
<artifactId>checkstyle</artifactId>
115-
<version>12.1.2</version>
115+
<version>13.0.0</version>
116116
</dependency>
117117
</dependencies>
118118
</plugin>
@@ -127,7 +127,7 @@
127127
<plugin>
128128
<groupId>com.mebigfatguy.fb-contrib</groupId>
129129
<artifactId>fb-contrib</artifactId>
130-
<version>7.7.0</version>
130+
<version>7.7.2</version>
131131
</plugin>
132132
<plugin>
133133
<groupId>com.h3xstream.findsecbugs</groupId>

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

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,36 @@
44
import java.util.List;
55

66
/**
7-
* Program description - To find all possible paths from source to destination
8-
* <a href="https://en.wikipedia.org/wiki/Shortest_path_problem">Wikipedia</a>
7+
* Finds all possible simple paths from a given source vertex to a destination vertex
8+
* in a directed graph using backtracking.
99
*
10-
* @author <a href="https://github.com/siddhant2002">Siddhant Swarup Mallick</a>
10+
* <p>This algorithm performs a Depth First Search (DFS) traversal while keeping track
11+
* of visited vertices to avoid cycles. Whenever the destination vertex is reached,
12+
* the current path is stored as one valid path.</p>
13+
*
14+
* <p><b>Key Characteristics:</b></p>
15+
* <ul>
16+
* <li>Works on directed graphs</li>
17+
* <li>Does not allow revisiting vertices in the same path</li>
18+
* <li>Stores all possible paths from source to destination</li>
19+
* </ul>
20+
*
21+
* <p><b>Time Complexity:</b></p>
22+
* <ul>
23+
* <li>Worst Case: O(V!) — when the graph is fully connected</li>
24+
* </ul>
25+
*
26+
* <p><b>Space Complexity:</b></p>
27+
* <ul>
28+
* <li>O(V) for recursion stack and visited array</li>
29+
* <li>Additional space for storing all valid paths</li>
30+
* </ul>
31+
*
32+
* <p>This implementation is intended for educational purposes.</p>
33+
*
34+
* @see <a href="https://en.wikipedia.org/wiki/Depth-first_search">Depth First Search</a>
1135
*/
36+
1237
@SuppressWarnings({"rawtypes", "unchecked"})
1338
public class AllPathsFromSourceToTarget {
1439

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package com.thealgorithms.ciphers;
2+
3+
import java.security.SecureRandom;
4+
import java.util.Objects;
5+
6+
/**
7+
* One-Time Pad (OTP) cipher implementation.
8+
*
9+
* <p>The One-Time Pad is information-theoretically secure if:
10+
* <ul>
11+
* <li>The key is truly random.</li>
12+
* <li>The key length is at least as long as the plaintext.</li>
13+
* <li>The key is used only once and kept secret.</li>
14+
* </ul>
15+
*
16+
* <p>This implementation is for <b>educational purposes only</b> and should not be
17+
* used in production systems.
18+
*/
19+
public final class OneTimePadCipher {
20+
21+
private static final SecureRandom RANDOM = new SecureRandom();
22+
23+
private OneTimePadCipher() {
24+
// utility class
25+
}
26+
27+
/**
28+
* Generates a random key of the given length in bytes.
29+
*
30+
* @param length the length of the key in bytes, must be non-negative
31+
* @return a new random key
32+
* @throws IllegalArgumentException if length is negative
33+
*/
34+
public static byte[] generateKey(int length) {
35+
if (length < 0) {
36+
throw new IllegalArgumentException("length must be non-negative");
37+
}
38+
byte[] key = new byte[length];
39+
RANDOM.nextBytes(key);
40+
return key;
41+
}
42+
43+
/**
44+
* Encrypts the given plaintext bytes using the provided key.
45+
* <p>The key length must be exactly the same as the plaintext length.
46+
*
47+
* @param plaintext the plaintext bytes, must not be {@code null}
48+
* @param key the one-time pad key bytes, must not be {@code null}
49+
* @return the ciphertext bytes
50+
* @throws IllegalArgumentException if the key length does not match plaintext length
51+
* @throws NullPointerException if plaintext or key is {@code null}
52+
*/
53+
public static byte[] encrypt(byte[] plaintext, byte[] key) {
54+
validateInputs(plaintext, key);
55+
return xor(plaintext, key);
56+
}
57+
58+
/**
59+
* Decrypts the given ciphertext bytes using the provided key.
60+
* <p>For a One-Time Pad, decryption is identical to encryption:
61+
* {@code plaintext = ciphertext XOR key}.
62+
*
63+
* @param ciphertext the ciphertext bytes, must not be {@code null}
64+
* @param key the one-time pad key bytes, must not be {@code null}
65+
* @return the decrypted plaintext bytes
66+
* @throws IllegalArgumentException if the key length does not match ciphertext length
67+
* @throws NullPointerException if ciphertext or key is {@code null}
68+
*/
69+
public static byte[] decrypt(byte[] ciphertext, byte[] key) {
70+
validateInputs(ciphertext, key);
71+
return xor(ciphertext, key);
72+
}
73+
74+
private static void validateInputs(byte[] input, byte[] key) {
75+
Objects.requireNonNull(input, "input must not be null");
76+
Objects.requireNonNull(key, "key must not be null");
77+
if (input.length != key.length) {
78+
throw new IllegalArgumentException("Key length must match input length");
79+
}
80+
}
81+
82+
private static byte[] xor(byte[] data, byte[] key) {
83+
byte[] result = new byte[data.length];
84+
for (int i = 0; i < data.length; i++) {
85+
result[i] = (byte) (data[i] ^ key[i]);
86+
}
87+
return result;
88+
}
89+
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package com.thealgorithms.datastructures.hashmap.hashing;
2+
3+
/**
4+
* Immutable HashMap implementation using separate chaining.
5+
*
6+
* <p>This HashMap does not allow modification of existing instances.
7+
* Any update operation returns a new ImmutableHashMap.
8+
*
9+
* @param <K> key type
10+
* @param <V> value type
11+
*/
12+
public final class ImmutableHashMap<K, V> {
13+
14+
private static final int DEFAULT_CAPACITY = 16;
15+
16+
private final Node<K, V>[] table;
17+
private final int size;
18+
19+
/**
20+
* Private constructor to enforce immutability.
21+
*/
22+
private ImmutableHashMap(Node<K, V>[] table, int size) {
23+
this.table = table;
24+
this.size = size;
25+
}
26+
27+
/**
28+
* Creates an empty ImmutableHashMap.
29+
*
30+
* @param <K> key type
31+
* @param <V> value type
32+
* @return empty ImmutableHashMap
33+
*/
34+
@SuppressWarnings({"unchecked", "rawtypes"})
35+
public static <K, V> ImmutableHashMap<K, V> empty() {
36+
Node<K, V>[] table = (Node<K, V>[]) new Node[DEFAULT_CAPACITY];
37+
return new ImmutableHashMap<>(table, 0);
38+
}
39+
40+
/**
41+
* Returns a new ImmutableHashMap with the given key-value pair added.
42+
*
43+
* @param key key to add
44+
* @param value value to associate
45+
* @return new ImmutableHashMap instance
46+
*/
47+
public ImmutableHashMap<K, V> put(K key, V value) {
48+
Node<K, V>[] newTable = table.clone();
49+
int index = hash(key);
50+
51+
newTable[index] = new Node<>(key, value, newTable[index]);
52+
return new ImmutableHashMap<>(newTable, size + 1);
53+
}
54+
55+
/**
56+
* Retrieves the value associated with the given key.
57+
*
58+
* @param key key to search
59+
* @return value if found, otherwise null
60+
*/
61+
public V get(K key) {
62+
int index = hash(key);
63+
Node<K, V> current = table[index];
64+
65+
while (current != null) {
66+
if ((key == null && current.key == null) || (key != null && key.equals(current.key))) {
67+
return current.value;
68+
}
69+
current = current.next;
70+
}
71+
return null;
72+
}
73+
74+
/**
75+
* Checks whether the given key exists in the map.
76+
*
77+
* @param key key to check
78+
* @return true if key exists, false otherwise
79+
*/
80+
public boolean containsKey(K key) {
81+
return get(key) != null;
82+
}
83+
84+
/**
85+
* Returns the number of key-value pairs.
86+
*
87+
* @return size of the map
88+
*/
89+
public int size() {
90+
return size;
91+
}
92+
93+
/**
94+
* Computes hash index for a given key.
95+
*/
96+
private int hash(K key) {
97+
return key == null ? 0 : (key.hashCode() & Integer.MAX_VALUE) % table.length;
98+
}
99+
100+
/**
101+
* Node class for separate chaining.
102+
*/
103+
private static final class Node<K, V> {
104+
105+
private final K key;
106+
private final V value;
107+
private final Node<K, V> next;
108+
109+
private Node(K key, V value, Node<K, V> next) {
110+
this.key = key;
111+
this.value = value;
112+
this.next = next;
113+
}
114+
}
115+
}
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+
}

0 commit comments

Comments
 (0)