Skip to content

Commit 71ba8f8

Browse files
authored
Merge branch 'master' into testing/MinStackUsingTwoStacks
2 parents e843dcd + dd1a51b commit 71ba8f8

File tree

10 files changed

+212
-141
lines changed

10 files changed

+212
-141
lines changed
Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,65 @@
11
package com.thealgorithms.datastructures.disjointsetunion;
22

33
/**
4-
* Disjoint Set Union or DSU is useful for solving problems related to connected components,
5-
* cycle detection in graphs, and maintaining relationships in disjoint sets of data.
6-
* It is commonly employed in graph algorithms and problems.
4+
* Disjoint Set Union (DSU), also known as Union-Find, is a data structure that tracks a set of elements
5+
* partitioned into disjoint (non-overlapping) subsets. It supports two primary operations efficiently:
76
*
8-
* @see <a href="https://en.wikipedia.org/wiki/Disjoint-set_data_structure">Disjoint Set Union</a>
7+
* <ul>
8+
* <li>Find: Determine which subset a particular element belongs to.</li>
9+
* <li>Union: Merge two subsets into a single subset.</li>
10+
* </ul>
11+
*
12+
* @see <a href="https://en.wikipedia.org/wiki/Disjoint-set_data_structure">Disjoint Set Union (Wikipedia)</a>
913
*/
1014
public class DisjointSetUnion<T> {
1115

1216
/**
13-
* Creates a new node of DSU with parent initialised as same node
17+
* Creates a new disjoint set containing the single specified element.
18+
*
19+
* @param value the element to be placed in a new singleton set
20+
* @return a node representing the new set
1421
*/
15-
public Node<T> makeSet(final T x) {
16-
return new Node<T>(x);
22+
public Node<T> makeSet(final T value) {
23+
return new Node<>(value);
1724
}
1825

1926
/**
20-
* Finds and returns the representative (root) element of the set to which a given element belongs.
21-
* This operation uses path compression to optimize future findSet operations.
27+
* Finds and returns the representative (root) of the set containing the given node.
28+
* This method applies path compression to flatten the tree structure for future efficiency.
29+
*
30+
* @param node the node whose set representative is to be found
31+
* @return the representative (root) node of the set
2232
*/
2333
public Node<T> findSet(Node<T> node) {
24-
while (node != node.parent) {
25-
node = node.parent;
34+
if (node != node.parent) {
35+
node.parent = findSet(node.parent);
2636
}
27-
return node;
37+
return node.parent;
2838
}
2939

3040
/**
31-
* Unions two sets by merging their representative elements. The merge is performed based on the rank of each set
32-
* to ensure efficient merging and path compression to optimize future findSet operations.
41+
* Merges the sets containing the two given nodes. Union by rank is used to attach the smaller tree under the larger one.
42+
* If both sets have the same rank, one becomes the parent and its rank is incremented.
43+
*
44+
* @param x a node in the first set
45+
* @param y a node in the second set
3346
*/
34-
public void unionSets(final Node<T> x, final Node<T> y) {
35-
Node<T> nx = findSet(x);
36-
Node<T> ny = findSet(y);
47+
public void unionSets(Node<T> x, Node<T> y) {
48+
Node<T> rootX = findSet(x);
49+
Node<T> rootY = findSet(y);
3750

38-
if (nx == ny) {
39-
return; // Both elements already belong to the same set.
51+
if (rootX == rootY) {
52+
return; // They are already in the same set
4053
}
4154
// Merging happens based on rank of node, this is done to avoid long chaining of nodes and reduce time
4255
// to find root of the component. Idea is to attach small components in big, instead of other way around.
43-
if (nx.rank > ny.rank) {
44-
ny.parent = nx;
45-
} else if (ny.rank > nx.rank) {
46-
nx.parent = ny;
56+
if (rootX.rank > rootY.rank) {
57+
rootY.parent = rootX;
58+
} else if (rootY.rank > rootX.rank) {
59+
rootX.parent = rootY;
4760
} else {
48-
// Both sets have the same rank; choose one as the parent and increment the rank.
49-
ny.parent = nx;
50-
nx.rank++;
61+
rootY.parent = rootX;
62+
rootX.rank++;
5163
}
5264
}
5365
}

src/main/java/com/thealgorithms/datastructures/hashmap/hashing/Intersection.java

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,60 +8,66 @@
88

99
/**
1010
* The {@code Intersection} class provides a method to compute the intersection of two integer arrays.
11-
* The intersection is defined as the set of common elements present in both arrays.
1211
* <p>
13-
* This class utilizes a HashMap to efficiently count occurrences of elements in the first array,
14-
* allowing for an efficient lookup of common elements in the second array.
12+
* This intersection includes duplicate values — meaning elements are included in the result
13+
* as many times as they appear in both arrays (i.e., multiset intersection).
1514
* </p>
1615
*
1716
* <p>
18-
* Example:
19-
* <pre>
17+
* The algorithm uses a {@link java.util.HashMap} to count occurrences of elements in the first array,
18+
* then iterates through the second array to collect common elements based on these counts.
19+
* </p>
20+
*
21+
* <p>
22+
* Example usage:
23+
* <pre>{@code
2024
* int[] array1 = {1, 2, 2, 1};
2125
* int[] array2 = {2, 2};
22-
* List<Integer> result = Intersection.intersection(array1, array2); // result will contain [2, 2]
23-
* </pre>
26+
* List<Integer> result = Intersection.intersection(array1, array2); // result: [2, 2]
27+
* }</pre>
2428
* </p>
2529
*
2630
* <p>
27-
* Note: The order of the returned list may vary since it depends on the order of elements
28-
* in the input arrays.
31+
* Note: The order of elements in the returned list depends on the order in the second input array.
2932
* </p>
3033
*/
3134
public final class Intersection {
3235

36+
private Intersection() {
37+
// Utility class; prevent instantiation
38+
}
39+
3340
/**
34-
* Computes the intersection of two integer arrays.
41+
* Computes the intersection of two integer arrays, preserving element frequency.
42+
* For example, given [1,2,2,3] and [2,2,4], the result will be [2,2].
43+
*
3544
* Steps:
36-
* 1. Count the occurrences of each element in the first array using a HashMap.
37-
* 2. Iterate over the second array and check if the element is present in the HashMap.
38-
* If it is, add it to the result list and decrement the count in the HashMap.
39-
* 3. Return the result list containing the intersection of the two arrays.
45+
* 1. Count the occurrences of each element in the first array using a map.
46+
* 2. Iterate over the second array and collect common elements.
4047
*
4148
* @param arr1 the first array of integers
4249
* @param arr2 the second array of integers
43-
* @return a list containing the intersection of the two arrays, or an empty list if either array is null or empty
50+
* @return a list containing the intersection of the two arrays (with duplicates),
51+
* or an empty list if either array is null or empty
4452
*/
4553
public static List<Integer> intersection(int[] arr1, int[] arr2) {
4654
if (arr1 == null || arr2 == null || arr1.length == 0 || arr2.length == 0) {
4755
return Collections.emptyList();
4856
}
4957

50-
Map<Integer, Integer> cnt = new HashMap<>(16);
51-
for (int v : arr1) {
52-
cnt.put(v, cnt.getOrDefault(v, 0) + 1);
58+
Map<Integer, Integer> countMap = new HashMap<>();
59+
for (int num : arr1) {
60+
countMap.put(num, countMap.getOrDefault(num, 0) + 1);
5361
}
5462

55-
List<Integer> res = new ArrayList<>();
56-
for (int v : arr2) {
57-
if (cnt.containsKey(v) && cnt.get(v) > 0) {
58-
res.add(v);
59-
cnt.put(v, cnt.get(v) - 1);
63+
List<Integer> result = new ArrayList<>();
64+
for (int num : arr2) {
65+
if (countMap.getOrDefault(num, 0) > 0) {
66+
result.add(num);
67+
countMap.computeIfPresent(num, (k, v) -> v - 1);
6068
}
6169
}
62-
return res;
63-
}
6470

65-
private Intersection() {
71+
return result;
6672
}
6773
}

src/main/java/com/thealgorithms/datastructures/hashmap/hashing/MajorityElement.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package com.thealgorithms.datastructures.hashmap.hashing;
22

33
import java.util.ArrayList;
4+
import java.util.Collections;
45
import java.util.HashMap;
56
import java.util.List;
7+
import java.util.Map;
68

79
/**
810
* This class provides a method to find the majority element(s) in an array of integers.
@@ -18,13 +20,18 @@ private MajorityElement() {
1820
* Returns a list of majority element(s) from the given array of integers.
1921
*
2022
* @param nums an array of integers
21-
* @return a list containing the majority element(s); returns an empty list if none exist
23+
* @return a list containing the majority element(s); returns an empty list if none exist or input is null/empty
2224
*/
2325
public static List<Integer> majority(int[] nums) {
24-
HashMap<Integer, Integer> numToCount = new HashMap<>();
26+
if (nums == null || nums.length == 0) {
27+
return Collections.emptyList();
28+
}
29+
30+
Map<Integer, Integer> numToCount = new HashMap<>();
2531
for (final var num : nums) {
2632
numToCount.merge(num, 1, Integer::sum);
2733
}
34+
2835
List<Integer> majorityElements = new ArrayList<>();
2936
for (final var entry : numToCount.entrySet()) {
3037
if (entry.getValue() >= nums.length / 2) {
Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,39 @@
11
package com.thealgorithms.dynamicprogramming;
2-
/*
3-
The Sum of Subset problem determines whether a subset of elements from a
4-
given array sums up to a specific target value.
5-
*/
2+
3+
/**
4+
* Utility class for solving the Subset Sum problem using a space-optimized dynamic programming approach.
5+
*
6+
* <p>This algorithm determines whether any subset of a given array sums up to a specific target value.</p>
7+
*
8+
* <p><b>Time Complexity:</b> O(n * sum)</p>
9+
* <p><b>Space Complexity:</b> O(sum)</p>
10+
*/
611
public final class SubsetSumSpaceOptimized {
712
private SubsetSumSpaceOptimized() {
813
}
14+
915
/**
10-
* This method checks whether the subset of an array
11-
* contains a given sum or not. This is an space
12-
* optimized solution using 1D boolean array
13-
* Time Complexity: O(n * sum), Space complexity: O(sum)
16+
* Determines whether there exists a subset of the given array that adds up to the specified sum.
17+
* This method uses a space-optimized dynamic programming approach with a 1D boolean array.
1418
*
15-
* @param arr An array containing integers
16-
* @param sum The target sum of the subset
17-
* @return True or False
19+
* @param nums The array of non-negative integers
20+
* @param targetSum The desired subset sum
21+
* @return {@code true} if such a subset exists, {@code false} otherwise
1822
*/
19-
public static boolean isSubsetSum(int[] arr, int sum) {
20-
int n = arr.length;
21-
// Declare the boolean array with size sum + 1
22-
boolean[] dp = new boolean[sum + 1];
23+
public static boolean isSubsetSum(int[] nums, int targetSum) {
24+
if (targetSum < 0) {
25+
return false; // Subset sum can't be negative
26+
}
2327

24-
// Initialize the first element as true
25-
dp[0] = true;
28+
boolean[] dp = new boolean[targetSum + 1];
29+
dp[0] = true; // Empty subset always sums to 0
2630

27-
// Find the subset sum using 1D array
28-
for (int i = 0; i < n; i++) {
29-
for (int j = sum; j >= arr[i]; j--) {
30-
dp[j] = dp[j] || dp[j - arr[i]];
31+
for (int number : nums) {
32+
for (int j = targetSum; j >= number; j--) {
33+
dp[j] = dp[j] || dp[j - number];
3134
}
3235
}
33-
return dp[sum];
36+
37+
return dp[targetSum];
3438
}
3539
}

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

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,24 +23,21 @@ public static double[] convolution(double[] a, double[] b) {
2323
double[] convolved = new double[a.length + b.length - 1];
2424

2525
/*
26-
The discrete convolution of two signals A and B is defined as:
27-
28-
A.length
29-
C[i] = Σ (A[k]*B[i-k])
30-
k=0
31-
32-
It's obvious that: 0 <= k <= A.length , 0 <= i <= A.length + B.length - 2 and 0 <= i-k <=
33-
B.length - 1 From the last inequality we get that: i - B.length + 1 <= k <= i and thus we get
34-
the conditions below.
26+
* Discrete convolution formula:
27+
* C[i] = Σ A[k] * B[i - k]
28+
* where k ranges over valid indices so that both A[k] and B[i-k] are in bounds.
3529
*/
30+
3631
for (int i = 0; i < convolved.length; i++) {
37-
convolved[i] = 0;
38-
int k = Math.max(i - b.length + 1, 0);
32+
double sum = 0;
33+
int kStart = Math.max(0, i - b.length + 1);
34+
int kEnd = Math.min(i, a.length - 1);
3935

40-
while (k < i + 1 && k < a.length) {
41-
convolved[i] += a[k] * b[i - k];
42-
k++;
36+
for (int k = kStart; k <= kEnd; k++) {
37+
sum += a[k] * b[i - k];
4338
}
39+
40+
convolved[i] = sum;
4441
}
4542

4643
return convolved;

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

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,46 +3,49 @@
33
import java.util.ArrayList;
44
import java.util.Collections;
55
import java.util.HashMap;
6+
import java.util.List;
7+
import java.util.Map;
68

7-
/*
8-
* Find the mode of an array of numbers
9-
*
10-
* The mode of an array of numbers is the most frequently occurring number in the array,
11-
* or the most frequently occurring numbers if there are multiple numbers with the same frequency
9+
/**
10+
* Utility class to calculate the mode(s) of an array of integers.
11+
* <p>
12+
* The mode of an array is the integer value(s) that occur most frequently.
13+
* If multiple values have the same highest frequency, all such values are returned.
14+
* </p>
1215
*/
1316
public final class Mode {
1417
private Mode() {
1518
}
1619

17-
/*
18-
* Find the mode of an array of integers
20+
/**
21+
* Computes the mode(s) of the specified array of integers.
22+
* <p>
23+
* If the input array is empty, this method returns {@code null}.
24+
* If multiple numbers share the highest frequency, all are returned in the result array.
25+
* </p>
1926
*
20-
* @param numbers array of integers
21-
* @return mode of the array
27+
* @param numbers an array of integers to analyze
28+
* @return an array containing the mode(s) of the input array, or {@code null} if the input is empty
2229
*/
2330
public static int[] mode(final int[] numbers) {
2431
if (numbers.length == 0) {
2532
return null;
2633
}
2734

28-
HashMap<Integer, Integer> count = new HashMap<>();
35+
Map<Integer, Integer> count = new HashMap<>();
2936

3037
for (int num : numbers) {
31-
if (count.containsKey(num)) {
32-
count.put(num, count.get(num) + 1);
33-
} else {
34-
count.put(num, 1);
35-
}
38+
count.put(num, count.getOrDefault(num, 0) + 1);
3639
}
3740

3841
int max = Collections.max(count.values());
39-
ArrayList<Integer> modes = new ArrayList<>();
42+
List<Integer> modes = new ArrayList<>();
4043

4144
for (final var entry : count.entrySet()) {
4245
if (entry.getValue() == max) {
4346
modes.add(entry.getKey());
4447
}
4548
}
46-
return modes.stream().mapToInt(n -> n).toArray();
49+
return modes.stream().mapToInt(Integer::intValue).toArray();
4750
}
4851
}

0 commit comments

Comments
 (0)