From df8fd850584077c8a15039301d52c9efd1400dbc Mon Sep 17 00:00:00 2001 From: Prashant Maurya Date: Tue, 14 Apr 2026 15:29:22 +0530 Subject: [PATCH 1/8] docs: add edge cases to JumpSearch documentation (#7379) * docs: add edge cases to JumpSearch documentation * fix: remove trailing whitespace (checkstyle) --- src/main/java/com/thealgorithms/searches/JumpSearch.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/com/thealgorithms/searches/JumpSearch.java b/src/main/java/com/thealgorithms/searches/JumpSearch.java index cbc494c8c16a..5074aa7845c8 100644 --- a/src/main/java/com/thealgorithms/searches/JumpSearch.java +++ b/src/main/java/com/thealgorithms/searches/JumpSearch.java @@ -36,6 +36,13 @@ * Space Complexity: O(1) - only uses a constant amount of extra space * *

+ * Edge Cases: + *

+ *

* Note: Jump Search requires a sorted array. For unsorted arrays, use Linear Search. * Compared to Linear Search (O(n)), Jump Search is faster for large arrays. * Compared to Binary Search (O(log n)), Jump Search is less efficient but may be From 14b6f9924216e5e0c4c2c70683c930bac369c1b9 Mon Sep 17 00:00:00 2001 From: Nick Zerjeski <57059725+nickzerjeski@users.noreply.github.com> Date: Tue, 14 Apr 2026 12:03:00 +0200 Subject: [PATCH 2/8] test(searches): cover null input cases in IterativeBinarySearch (#7375) --- .../searches/IterativeBinarySearchTest.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/test/java/com/thealgorithms/searches/IterativeBinarySearchTest.java b/src/test/java/com/thealgorithms/searches/IterativeBinarySearchTest.java index b2e121ac1ba0..f291610b298b 100644 --- a/src/test/java/com/thealgorithms/searches/IterativeBinarySearchTest.java +++ b/src/test/java/com/thealgorithms/searches/IterativeBinarySearchTest.java @@ -87,6 +87,26 @@ void testBinarySearchEmptyArray() { assertEquals(-1, binarySearch.find(array, key), "The element should not be found in an empty array."); } + /** + * Test for binary search with a null array. + */ + @Test + void testBinarySearchNullArray() { + IterativeBinarySearch binarySearch = new IterativeBinarySearch(); + Integer key = 1; + assertEquals(-1, binarySearch.find(null, key), "The element should not be found in a null array."); + } + + /** + * Test for binary search with a null key. + */ + @Test + void testBinarySearchNullKey() { + IterativeBinarySearch binarySearch = new IterativeBinarySearch(); + Integer[] array = {1, 2, 4, 8, 16}; + assertEquals(-1, binarySearch.find(array, null), "A null search key should return -1."); + } + /** * Test for binary search on a large array. */ From b3e31b5a5cd1465e474b71d87b44d4659fcfda23 Mon Sep 17 00:00:00 2001 From: Nick Zerjeski <57059725+nickzerjeski@users.noreply.github.com> Date: Wed, 15 Apr 2026 16:07:03 +0200 Subject: [PATCH 3/8] feat(graph): add DSU-based account merge algorithm (#7377) * feat(graph): add DSU-based account merge algorithm * test(graph): add null and transitive account merge cases * Handle no-email accounts in account merge * Apply clang-format style to account merge tests --- .../com/thealgorithms/graph/AccountMerge.java | 112 ++++++++++++++++++ .../thealgorithms/graph/AccountMergeTest.java | 61 ++++++++++ 2 files changed, 173 insertions(+) create mode 100644 src/main/java/com/thealgorithms/graph/AccountMerge.java create mode 100644 src/test/java/com/thealgorithms/graph/AccountMergeTest.java diff --git a/src/main/java/com/thealgorithms/graph/AccountMerge.java b/src/main/java/com/thealgorithms/graph/AccountMerge.java new file mode 100644 index 000000000000..cf934a72eb68 --- /dev/null +++ b/src/main/java/com/thealgorithms/graph/AccountMerge.java @@ -0,0 +1,112 @@ +package com.thealgorithms.graph; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * Merges account records using Disjoint Set Union (Union-Find) on shared emails. + * + *

Input format: each account is a list where the first element is the user name and the + * remaining elements are emails. + */ +public final class AccountMerge { + private AccountMerge() { + } + + public static List> mergeAccounts(List> accounts) { + if (accounts == null || accounts.isEmpty()) { + return List.of(); + } + + UnionFind dsu = new UnionFind(accounts.size()); + Map emailToAccount = new HashMap<>(); + + for (int i = 0; i < accounts.size(); i++) { + List account = accounts.get(i); + for (int j = 1; j < account.size(); j++) { + String email = account.get(j); + Integer previous = emailToAccount.putIfAbsent(email, i); + if (previous != null) { + dsu.union(i, previous); + } + } + } + + Map> rootToEmails = new LinkedHashMap<>(); + for (Map.Entry entry : emailToAccount.entrySet()) { + int root = dsu.find(entry.getValue()); + rootToEmails.computeIfAbsent(root, ignored -> new ArrayList<>()).add(entry.getKey()); + } + for (int i = 0; i < accounts.size(); i++) { + if (accounts.get(i).size() <= 1) { + int root = dsu.find(i); + rootToEmails.computeIfAbsent(root, ignored -> new ArrayList<>()); + } + } + + List> merged = new ArrayList<>(); + for (Map.Entry> entry : rootToEmails.entrySet()) { + int root = entry.getKey(); + List emails = entry.getValue(); + Collections.sort(emails); + + List mergedAccount = new ArrayList<>(); + mergedAccount.add(accounts.get(root).getFirst()); + mergedAccount.addAll(emails); + merged.add(mergedAccount); + } + + merged.sort((a, b) -> { + int cmp = a.getFirst().compareTo(b.getFirst()); + if (cmp != 0) { + return cmp; + } + if (a.size() == 1 || b.size() == 1) { + return Integer.compare(a.size(), b.size()); + } + return a.get(1).compareTo(b.get(1)); + }); + return merged; + } + + private static final class UnionFind { + private final int[] parent; + private final int[] rank; + + private UnionFind(int size) { + this.parent = new int[size]; + this.rank = new int[size]; + for (int i = 0; i < size; i++) { + parent[i] = i; + } + } + + private int find(int x) { + if (parent[x] != x) { + parent[x] = find(parent[x]); + } + return parent[x]; + } + + private void union(int x, int y) { + int rootX = find(x); + int rootY = find(y); + if (rootX == rootY) { + return; + } + + if (rank[rootX] < rank[rootY]) { + parent[rootX] = rootY; + } else if (rank[rootX] > rank[rootY]) { + parent[rootY] = rootX; + } else { + parent[rootY] = rootX; + rank[rootX]++; + } + } + } +} diff --git a/src/test/java/com/thealgorithms/graph/AccountMergeTest.java b/src/test/java/com/thealgorithms/graph/AccountMergeTest.java new file mode 100644 index 000000000000..291be677d894 --- /dev/null +++ b/src/test/java/com/thealgorithms/graph/AccountMergeTest.java @@ -0,0 +1,61 @@ +package com.thealgorithms.graph; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.List; +import org.junit.jupiter.api.Test; + +class AccountMergeTest { + + @Test + void testMergeAccountsWithSharedEmails() { + List> accounts = List.of(List.of("abc", "abc@mail.com", "abx@mail.com"), List.of("abc", "abc@mail.com", "aby@mail.com"), List.of("Mary", "mary@mail.com"), List.of("John", "johnnybravo@mail.com")); + + List> merged = AccountMerge.mergeAccounts(accounts); + + List> expected = List.of(List.of("John", "johnnybravo@mail.com"), List.of("Mary", "mary@mail.com"), List.of("abc", "abc@mail.com", "abx@mail.com", "aby@mail.com")); + + assertEquals(expected, merged); + } + + @Test + void testAccountsWithSameNameButNoSharedEmailStaySeparate() { + List> accounts = List.of(List.of("Alex", "alex1@mail.com"), List.of("Alex", "alex2@mail.com")); + + List> merged = AccountMerge.mergeAccounts(accounts); + List> expected = List.of(List.of("Alex", "alex1@mail.com"), List.of("Alex", "alex2@mail.com")); + + assertEquals(expected, merged); + } + + @Test + void testEmptyInput() { + assertEquals(List.of(), AccountMerge.mergeAccounts(List.of())); + } + + @Test + void testNullInput() { + assertEquals(List.of(), AccountMerge.mergeAccounts(null)); + } + + @Test + void testTransitiveMergeAndDuplicateEmails() { + List> accounts = List.of(List.of("A", "a1@mail.com", "a2@mail.com"), List.of("A", "a2@mail.com", "a3@mail.com"), List.of("A", "a3@mail.com", "a4@mail.com", "a4@mail.com")); + + List> merged = AccountMerge.mergeAccounts(accounts); + + List> expected = List.of(List.of("A", "a1@mail.com", "a2@mail.com", "a3@mail.com", "a4@mail.com")); + + assertEquals(expected, merged); + } + + @Test + void testAccountsWithNoEmailsArePreserved() { + List> accounts = List.of(List.of("Alex"), List.of("Alex", "alex1@mail.com"), List.of("Bob")); + + List> merged = AccountMerge.mergeAccounts(accounts); + List> expected = List.of(List.of("Alex"), List.of("Alex", "alex1@mail.com"), List.of("Bob")); + + assertEquals(expected, merged); + } +} From 0ad5d90012095fc90f3fba4ec28560421f7e0844 Mon Sep 17 00:00:00 2001 From: Senrian <47714364+Senrian@users.noreply.github.com> Date: Wed, 22 Apr 2026 17:26:20 +0800 Subject: [PATCH 4/8] fix: remove malformed javadoc to fix -Werror build failure (#7393) (#7394) * fix: prevent NPE when array contains null elements When searching for a non-null key in an array that contains null elements, the sentinel linear search would throw a NullPointerException because it called array[i].compareTo(key) without checking if array[i] is null. Added null check for array[i] in the while loop condition to prevent NPE and return the correct index when array elements themselves are null. Issue: #7318 (related) * fix: remove malformed @author javadoc in AnyBaseToAnyBase (issue #7393) * fix: remove malformed javadoc in ReverseString (part of issue #7393) --------- Co-authored-by: OpenClaw Agent Co-authored-by: OpenClaw Bot Co-authored-by: Deniz Altunkapan --- .../java/com/thealgorithms/conversions/AnyBaseToAnyBase.java | 2 +- .../java/com/thealgorithms/searches/SentinelLinearSearch.java | 3 ++- src/main/java/com/thealgorithms/strings/ReverseString.java | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/thealgorithms/conversions/AnyBaseToAnyBase.java b/src/main/java/com/thealgorithms/conversions/AnyBaseToAnyBase.java index 7698cc832981..3d31cb3e7f6c 100644 --- a/src/main/java/com/thealgorithms/conversions/AnyBaseToAnyBase.java +++ b/src/main/java/com/thealgorithms/conversions/AnyBaseToAnyBase.java @@ -3,7 +3,7 @@ *

* Time Complexity: O(n) [or appropriate complexity] * Space Complexity: O(n) - * * @author Reshma Kakkirala + * @author Reshma Kakkirala */ package com.thealgorithms.conversions; diff --git a/src/main/java/com/thealgorithms/searches/SentinelLinearSearch.java b/src/main/java/com/thealgorithms/searches/SentinelLinearSearch.java index 1a5903a5d134..473fc2c3f094 100644 --- a/src/main/java/com/thealgorithms/searches/SentinelLinearSearch.java +++ b/src/main/java/com/thealgorithms/searches/SentinelLinearSearch.java @@ -65,7 +65,8 @@ public > int find(T[] array, T key) { int i = 0; // Search without bound checking since sentinel guarantees we'll find the key - while (array[i].compareTo(key) != 0) { + // Null check for array element to prevent NPE when array contains null elements + while (array[i] != null && array[i].compareTo(key) != 0) { i++; } diff --git a/src/main/java/com/thealgorithms/strings/ReverseString.java b/src/main/java/com/thealgorithms/strings/ReverseString.java index 7b918ebe1a59..e373dd0b7174 100644 --- a/src/main/java/com/thealgorithms/strings/ReverseString.java +++ b/src/main/java/com/thealgorithms/strings/ReverseString.java @@ -62,7 +62,7 @@ public static String reverse3(String string) { /** * Reverses the given string using a stack. * This method uses a stack to reverse the characters of the string. - * * @param str The input string to be reversed. + * @param str The input string to be reversed. * @return The reversed string. */ public static String reverseStringUsingStack(String str) { From 763b95b69b33f790093d1eae3599dfcc47f2a4c7 Mon Sep 17 00:00:00 2001 From: orbisai0security Date: Wed, 22 Apr 2026 22:53:28 +0530 Subject: [PATCH 5/8] fix: aesencryption in AESEncryption.java (#7392) fix: V-001 security vulnerability Automated security fix generated by Orbis Security AI --- src/main/java/com/thealgorithms/ciphers/AESEncryption.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/thealgorithms/ciphers/AESEncryption.java b/src/main/java/com/thealgorithms/ciphers/AESEncryption.java index 14582205442f..6f155e73f47d 100644 --- a/src/main/java/com/thealgorithms/ciphers/AESEncryption.java +++ b/src/main/java/com/thealgorithms/ciphers/AESEncryption.java @@ -38,7 +38,7 @@ public static void main(String[] args) throws Exception { System.out.println("Original Text:" + plainText); System.out.println("AES Key (Hex Form):" + bytesToHex(secKey.getEncoded())); System.out.println("Encrypted Text (Hex Form):" + bytesToHex(cipherText)); - System.out.println("Descrypted Text:" + decryptedText); + System.out.println("Decryption successful. Decrypted text matches original: " + decryptedText.equals(plainText)); } /** From 35b94ab4f8214b1a939ae504b7b83ed5d071625e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 20:42:24 +0200 Subject: [PATCH 6/8] chore(deps): bump com.puppycrawl.tools:checkstyle from 13.4.0 to 13.4.1 (#7404) Bumps [com.puppycrawl.tools:checkstyle](https://github.com/checkstyle/checkstyle) from 13.4.0 to 13.4.1. - [Commits](https://github.com/checkstyle/checkstyle/compare/checkstyle-13.4.0...checkstyle-13.4.1) --- updated-dependencies: - dependency-name: com.puppycrawl.tools:checkstyle dependency-version: 13.4.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 74b6cd9bd485..2a543a6549d0 100644 --- a/pom.xml +++ b/pom.xml @@ -112,7 +112,7 @@ com.puppycrawl.tools checkstyle - 13.4.0 + 13.4.1 From 6db8e207669e7f1b689615222e7ee54c68dc4981 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 2 May 2026 22:16:55 +0200 Subject: [PATCH 7/8] chore(deps): bump com.puppycrawl.tools:checkstyle from 13.4.1 to 13.4.2 (#7411) Bumps [com.puppycrawl.tools:checkstyle](https://github.com/checkstyle/checkstyle) from 13.4.1 to 13.4.2. - [Release notes](https://github.com/checkstyle/checkstyle/releases) - [Commits](https://github.com/checkstyle/checkstyle/compare/checkstyle-13.4.1...checkstyle-13.4.2) --- updated-dependencies: - dependency-name: com.puppycrawl.tools:checkstyle dependency-version: 13.4.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2a543a6549d0..e0a3486b23bb 100644 --- a/pom.xml +++ b/pom.xml @@ -112,7 +112,7 @@ com.puppycrawl.tools checkstyle - 13.4.1 + 13.4.2 From 2616e0950feaa3ff2e4a1bc1d9e0530eb979e442 Mon Sep 17 00:00:00 2001 From: Abdul-Rehman-svg Date: Sun, 3 May 2026 17:30:16 +0500 Subject: [PATCH 8/8] Update Anagrams.java (#7409) fix: remove invalid reference [1] in Anagrams.java Co-authored-by: Deniz Altunkapan --- src/main/java/com/thealgorithms/strings/Anagrams.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/thealgorithms/strings/Anagrams.java b/src/main/java/com/thealgorithms/strings/Anagrams.java index 5b97af0758f2..7bd84d47508f 100644 --- a/src/main/java/com/thealgorithms/strings/Anagrams.java +++ b/src/main/java/com/thealgorithms/strings/Anagrams.java @@ -5,7 +5,7 @@ /** * An anagram is a word or phrase formed by rearranging the letters of a different word or phrase, - * typically using all the original letters exactly once.[1] + * typically using all the original letters exactly once. * For example, the word anagram itself can be rearranged into nag a ram, * also the word binary into brainy and the word adobe into abode. * Reference from https://en.wikipedia.org/wiki/Anagram