diff --git a/DIRECTORY.md b/DIRECTORY.md index deaf59636fa4..6d945ac16c3d 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -43,7 +43,6 @@ - πŸ“„ [FirstDifferentBit](src/main/java/com/thealgorithms/bitmanipulation/FirstDifferentBit.java) - πŸ“„ [GenerateSubsets](src/main/java/com/thealgorithms/bitmanipulation/GenerateSubsets.java) - πŸ“„ [GrayCodeConversion](src/main/java/com/thealgorithms/bitmanipulation/GrayCodeConversion.java) - - πŸ“„ [HammingDistance](src/main/java/com/thealgorithms/bitmanipulation/HammingDistance.java) - πŸ“„ [HigherLowerPowerOfTwo](src/main/java/com/thealgorithms/bitmanipulation/HigherLowerPowerOfTwo.java) - πŸ“„ [HighestSetBit](src/main/java/com/thealgorithms/bitmanipulation/HighestSetBit.java) - πŸ“„ [IndexOfRightMostSetBit](src/main/java/com/thealgorithms/bitmanipulation/IndexOfRightMostSetBit.java) @@ -346,7 +345,6 @@ - πŸ“„ [LongestIncreasingSubsequence](src/main/java/com/thealgorithms/dynamicprogramming/LongestIncreasingSubsequence.java) - πŸ“„ [LongestIncreasingSubsequenceNLogN](src/main/java/com/thealgorithms/dynamicprogramming/LongestIncreasingSubsequenceNLogN.java) - πŸ“„ [LongestPalindromicSubsequence](src/main/java/com/thealgorithms/dynamicprogramming/LongestPalindromicSubsequence.java) - - πŸ“„ [LongestPalindromicSubstring](src/main/java/com/thealgorithms/dynamicprogramming/LongestPalindromicSubstring.java) - πŸ“„ [LongestValidParentheses](src/main/java/com/thealgorithms/dynamicprogramming/LongestValidParentheses.java) - πŸ“„ [MatrixChainMultiplication](src/main/java/com/thealgorithms/dynamicprogramming/MatrixChainMultiplication.java) - πŸ“„ [MatrixChainRecursiveTopDownMemoisation](src/main/java/com/thealgorithms/dynamicprogramming/MatrixChainRecursiveTopDownMemoisation.java) @@ -406,7 +404,7 @@ - πŸ“„ [ActivitySelection](src/main/java/com/thealgorithms/greedyalgorithms/ActivitySelection.java) - πŸ“„ [BandwidthAllocation](src/main/java/com/thealgorithms/greedyalgorithms/BandwidthAllocation.java) - πŸ“„ [BinaryAddition](src/main/java/com/thealgorithms/greedyalgorithms/BinaryAddition.java) - - πŸ“„ [CoinChange](src/main/java/com/thealgorithms/greedyalgorithms/CoinChange.java) + - πŸ“„ [GreedyCoinChange](src/main/java/com/thealgorithms/greedyalgorithms/GreedyCoinChange.java) - πŸ“„ [DigitSeparation](src/main/java/com/thealgorithms/greedyalgorithms/DigitSeparation.java) - πŸ“„ [EgyptianFraction](src/main/java/com/thealgorithms/greedyalgorithms/EgyptianFraction.java) - πŸ“„ [FractionalKnapsack](src/main/java/com/thealgorithms/greedyalgorithms/FractionalKnapsack.java) @@ -595,7 +593,7 @@ - πŸ“„ [ArrayRightRotation](src/main/java/com/thealgorithms/others/ArrayRightRotation.java) - πŸ“„ [BFPRT](src/main/java/com/thealgorithms/others/BFPRT.java) - πŸ“„ [BankersAlgorithm](src/main/java/com/thealgorithms/others/BankersAlgorithm.java) - - πŸ“„ [BoyerMoore](src/main/java/com/thealgorithms/others/BoyerMoore.java) + - πŸ“„ [BoyerMooreMajorityVote](src/main/java/com/thealgorithms/others/BoyerMooreMajorityVote.java) - πŸ“„ [BrianKernighanAlgorithm](src/main/java/com/thealgorithms/others/BrianKernighanAlgorithm.java) - πŸ“„ [CRC16](src/main/java/com/thealgorithms/others/CRC16.java) - πŸ“„ [CRC32](src/main/java/com/thealgorithms/others/CRC32.java) @@ -627,7 +625,6 @@ - πŸ“„ [TwoPointers](src/main/java/com/thealgorithms/others/TwoPointers.java) - πŸ“„ [Verhoeff](src/main/java/com/thealgorithms/others/Verhoeff.java) - πŸ“ **cn** - - πŸ“„ [HammingDistance](src/main/java/com/thealgorithms/others/cn/HammingDistance.java) - πŸ“ **physics** - πŸ“„ [CoulombsLaw](src/main/java/com/thealgorithms/physics/CoulombsLaw.java) - πŸ“„ [DampedOscillator](src/main/java/com/thealgorithms/physics/DampedOscillator.java) @@ -834,7 +831,6 @@ - πŸ“„ [StringMatchFiniteAutomata](src/main/java/com/thealgorithms/strings/StringMatchFiniteAutomata.java) - πŸ“„ [SuffixArray](src/main/java/com/thealgorithms/strings/SuffixArray.java) - πŸ“„ [Upper](src/main/java/com/thealgorithms/strings/Upper.java) - - πŸ“„ [ValidParentheses](src/main/java/com/thealgorithms/strings/ValidParentheses.java) - πŸ“„ [WordLadder](src/main/java/com/thealgorithms/strings/WordLadder.java) - πŸ“„ [ZAlgorithm](src/main/java/com/thealgorithms/strings/ZAlgorithm.java) - πŸ“ **zigZagPattern** diff --git a/src/main/java/com/thealgorithms/bitmanipulation/HammingDistance.java b/src/main/java/com/thealgorithms/bitmanipulation/HammingDistance.java deleted file mode 100644 index 4c24909ef234..000000000000 --- a/src/main/java/com/thealgorithms/bitmanipulation/HammingDistance.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.thealgorithms.bitmanipulation; - -/** - * The Hamming distance between two integers is the number of positions at which the corresponding bits are different. - * Given two integers x and y, calculate the Hamming distance. - * Example: - * Input: x = 1, y = 4 - * Output: 2 - * Explanation: 1 (0001) and 4 (0100) have 2 differing bits. - * - * @author Hardvan - */ -public final class HammingDistance { - private HammingDistance() { - } - - /** - * Calculates the Hamming distance between two integers. - * The Hamming distance is the number of differing bits between the two integers. - * - * @param x The first integer. - * @param y The second integer. - * @return The Hamming distance (number of differing bits). - */ - public static int hammingDistance(int x, int y) { - int xor = x ^ y; - return Integer.bitCount(xor); - } -} diff --git a/src/main/java/com/thealgorithms/dynamicprogramming/LongestPalindromicSubstring.java b/src/main/java/com/thealgorithms/dynamicprogramming/LongestPalindromicSubstring.java deleted file mode 100644 index 8a4ab2f526a9..000000000000 --- a/src/main/java/com/thealgorithms/dynamicprogramming/LongestPalindromicSubstring.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.thealgorithms.dynamicprogramming; - -/** - * Class for finding the longest palindromic substring within a given string. - *

- * A palindromic substring is a sequence of characters that reads the same backward as forward. - * This class uses a dynamic programming approach to efficiently find the longest palindromic substring. - * - */ -public final class LongestPalindromicSubstring { - private LongestPalindromicSubstring() { - } - - public static String lps(String input) { - if (input == null || input.isEmpty()) { - return input; - } - boolean[][] arr = new boolean[input.length()][input.length()]; - int start = 0; - int end = 0; - for (int g = 0; g < input.length(); g++) { - for (int i = 0, j = g; j < input.length(); i++, j++) { - if (g == 0) { - arr[i][j] = true; - } else if (g == 1) { - arr[i][j] = input.charAt(i) == input.charAt(j); - } else { - arr[i][j] = input.charAt(i) == input.charAt(j) && arr[i + 1][j - 1]; - } - - if (arr[i][j]) { - start = i; - end = j; - } - } - } - return input.substring(start, end + 1); - } -} diff --git a/src/main/java/com/thealgorithms/greedyalgorithms/CoinChange.java b/src/main/java/com/thealgorithms/greedyalgorithms/CoinChange.java deleted file mode 100644 index 8054581d21d7..000000000000 --- a/src/main/java/com/thealgorithms/greedyalgorithms/CoinChange.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.thealgorithms.greedyalgorithms; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; - -// Problem Link : https://en.wikipedia.org/wiki/Change-making_problem - -public final class CoinChange { - private CoinChange() { - } - // Function to solve the coin change problem - public static ArrayList coinChangeProblem(int amount) { - // Define an array of coin denominations in descending order - Integer[] coins = {1, 2, 5, 10, 20, 50, 100, 500, 2000}; - - // Sort the coin denominations in descending order - Arrays.sort(coins, Comparator.reverseOrder()); - - ArrayList ans = new ArrayList<>(); // List to store selected coins - - // Iterate through the coin denominations - for (int i = 0; i < coins.length; i++) { - // Check if the current coin denomination can be used to reduce the remaining amount - if (coins[i] <= amount) { - // Repeatedly subtract the coin denomination from the remaining amount - while (coins[i] <= amount) { - ans.add(coins[i]); // Add the coin to the list of selected coins - amount -= coins[i]; // Update the remaining amount - } - } - } - return ans; - } -} diff --git a/src/main/java/com/thealgorithms/greedyalgorithms/GreedyCoinChange.java b/src/main/java/com/thealgorithms/greedyalgorithms/GreedyCoinChange.java new file mode 100644 index 000000000000..4aa4153fe226 --- /dev/null +++ b/src/main/java/com/thealgorithms/greedyalgorithms/GreedyCoinChange.java @@ -0,0 +1,43 @@ +package com.thealgorithms.greedyalgorithms; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; + +/** + * Greedy coin change (renamed for clarity). + * + *

Resolves naming conflict: "CoinChange" exists in both dynamicprogramming (DP: count combinations, + * minimum coins) and greedyalgorithms. This class is the greedy approach using fixed denominations. + * + *

Returns a list of coins that sum to the given amount using a greedy strategy with + * standard denominations (1, 2, 5, 10, 20, 50, 100, 500, 2000). + * + * @see Change-making problem + */ +public final class GreedyCoinChange { + private GreedyCoinChange() { + } + + /** + * Returns a list of coins (in descending order of use) that sum to the given amount. + * Uses greedy selection with fixed denominations. + * + * @param amount the target amount + * @return list of coin values that sum to amount (may be empty if amount is 0) + */ + public static ArrayList coinChangeProblem(int amount) { + Integer[] coins = {1, 2, 5, 10, 20, 50, 100, 500, 2000}; + Arrays.sort(coins, Comparator.reverseOrder()); + + ArrayList ans = new ArrayList<>(); + + for (Integer coin : coins) { + while (coin <= amount) { + ans.add(coin); + amount -= coin; + } + } + return ans; + } +} diff --git a/src/main/java/com/thealgorithms/others/BoyerMoore.java b/src/main/java/com/thealgorithms/others/BoyerMooreMajorityVote.java similarity index 53% rename from src/main/java/com/thealgorithms/others/BoyerMoore.java rename to src/main/java/com/thealgorithms/others/BoyerMooreMajorityVote.java index 3fb97724b5ac..7ad6889fd8ba 100644 --- a/src/main/java/com/thealgorithms/others/BoyerMoore.java +++ b/src/main/java/com/thealgorithms/others/BoyerMooreMajorityVote.java @@ -1,16 +1,19 @@ package com.thealgorithms.others; + import java.util.Optional; /** - * Utility class implementing Boyer-Moore's Voting Algorithm to find the majority element - * in an array. The majority element is defined as the element that appears more than n/2 times - * in the array, where n is the length of the array. + * Boyer-Moore Majority Vote Algorithm (renamed for clarity). + * + *

Resolves naming conflict: "BoyerMoore" in others referred to the majority vote algorithm, + * while searches.BoyerMoore is the string-search algorithm. This class is the majority-vote implementation. * - * For more information on the algorithm, refer to: - * https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_majority_vote_algorithm + *

Finds the majority element in an array (element that appears more than n/2 times). + * + * @see Boyer–Moore majority vote algorithm */ -public final class BoyerMoore { - private BoyerMoore() { +public final class BoyerMooreMajorityVote { + private BoyerMooreMajorityVote() { } /** @@ -33,12 +36,6 @@ public static Optional findMajorityElement(int[] array) { return Optional.empty(); } - /** - * Identifies the potential majority candidate using Boyer-Moore's Voting Algorithm. - * - * @param array the input array - * @return the candidate for the majority element - */ private static int findCandidate(final int[] array) { int count = 0; int candidate = -1; @@ -51,13 +48,6 @@ private static int findCandidate(final int[] array) { return candidate; } - /** - * Counts the occurrences of the candidate element in the array. - * - * @param candidate the candidate element - * @param array the input array - * @return the number of times the candidate appears in the array - */ private static int countOccurrences(final int candidate, final int[] array) { int count = 0; for (int value : array) { @@ -68,13 +58,6 @@ private static int countOccurrences(final int candidate, final int[] array) { return count; } - /** - * Determines if the count of the candidate element is more than n/2, where n is the length of the array. - * - * @param count the number of occurrences of the candidate - * @param totalCount the total number of elements in the array - * @return true if the candidate is the majority element, false otherwise - */ private static boolean isMajority(int count, int totalCount) { return 2 * count > totalCount; } diff --git a/src/main/java/com/thealgorithms/others/cn/HammingDistance.java b/src/main/java/com/thealgorithms/others/cn/HammingDistance.java deleted file mode 100644 index c8239d53d606..000000000000 --- a/src/main/java/com/thealgorithms/others/cn/HammingDistance.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.thealgorithms.others.cn; - -public final class HammingDistance { - private HammingDistance() { - } - - private static void checkChar(char inChar) { - if (inChar != '0' && inChar != '1') { - throw new IllegalArgumentException("Input must be a binary string."); - } - } - - public static int compute(char charA, char charB) { - checkChar(charA); - checkChar(charB); - return charA == charB ? 0 : 1; - } - - public static int compute(String bitsStrA, String bitsStrB) { - if (bitsStrA.length() != bitsStrB.length()) { - throw new IllegalArgumentException("Input strings must have the same length."); - } - - int totalErrorBitCount = 0; - - for (int i = 0; i < bitsStrA.length(); i++) { - totalErrorBitCount += compute(bitsStrA.charAt(i), bitsStrB.charAt(i)); - } - - return totalErrorBitCount; - } -} diff --git a/src/main/java/com/thealgorithms/stacks/ValidParentheses.java b/src/main/java/com/thealgorithms/stacks/ValidParentheses.java index 2cc616a38826..306852991a39 100644 --- a/src/main/java/com/thealgorithms/stacks/ValidParentheses.java +++ b/src/main/java/com/thealgorithms/stacks/ValidParentheses.java @@ -1,32 +1,26 @@ package com.thealgorithms.stacks; -import java.util.HashMap; +import java.util.ArrayDeque; +import java.util.Deque; import java.util.Map; -import java.util.Stack; /** - * Valid Parentheses Problem + * Valid Parentheses Problem (consolidated implementation). * - * Given a string containing just the characters '(', ')', '{', '}', '[' and ']', - * determine if the input string is valid. - * - * An input string is valid if: - * 1. Open brackets must be closed by the same type of brackets. - * 2. Open brackets must be closed in the correct order. - * 3. Every close bracket has a corresponding open bracket of the same type. - * - * Examples: - * Input: "()" - * Output: true + *

Resolves duplicate implementations: single stack-based solution for validating + * matching parentheses. Previously duplicated in strings and stacks packages. * - * Input: "()[]{}" - * Output: true + *

Given a string containing just the characters '(', ')', '{', '}', '[' and ']', + * determine if the input string is valid. * - * Input: "(]" - * Output: false + *

An input string is valid if: + *

* - * Input: "([)]" - * Output: false + *

Examples: "()" β†’ true, "()[]{}" β†’ true, "(]" β†’ false, "([)]" β†’ false. * * @author Gokul45-45 */ @@ -34,41 +28,37 @@ public final class ValidParentheses { private ValidParentheses() { } + // Map closing bracket to opening bracket for stack matching + private static final Map CLOSE_TO_OPEN = Map.of(')', '(', '}', '{', ']', '['); + private static final Map OPEN_TO_CLOSE = Map.of('(', ')', '{', '}', '[', ']'); + /** - * Checks if the given string has valid parentheses + * Checks if the given string has valid matching parentheses using a stack. + * Only the six bracket characters are allowed; any other character makes the string invalid. * - * @param s the input string containing parentheses - * @return true if valid, false otherwise + * @param s the input string (only bracket characters allowed) + * @return true if valid, false if null, odd length, contains non-bracket chars, or mismatched */ public static boolean isValid(String s) { if (s == null || s.length() % 2 != 0) { return false; } - Map parenthesesMap = new HashMap<>(); - parenthesesMap.put('(', ')'); - parenthesesMap.put('{', '}'); - parenthesesMap.put('[', ']'); - - Stack stack = new Stack<>(); + Deque stack = new ArrayDeque<>(); for (char c : s.toCharArray()) { - if (parenthesesMap.containsKey(c)) { - // Opening bracket - push to stack + if (OPEN_TO_CLOSE.containsKey(c)) { stack.push(c); - } else { - // Closing bracket - check if it matches - if (stack.isEmpty()) { - return false; - } - char openBracket = stack.pop(); - if (parenthesesMap.get(openBracket) != c) { + } else if (CLOSE_TO_OPEN.containsKey(c)) { + if (stack.isEmpty() || stack.pop() != CLOSE_TO_OPEN.get(c)) { return false; } + } else { + // Non-bracket character + return false; } } - // Stack should be empty if all brackets are matched return stack.isEmpty(); } } diff --git a/src/main/java/com/thealgorithms/strings/HammingDistance.java b/src/main/java/com/thealgorithms/strings/HammingDistance.java index 235e317d94f1..d135b3f72505 100644 --- a/src/main/java/com/thealgorithms/strings/HammingDistance.java +++ b/src/main/java/com/thealgorithms/strings/HammingDistance.java @@ -1,11 +1,13 @@ package com.thealgorithms.strings; /** - * Class for calculating the Hamming distance between two strings of equal length. - *

- * The Hamming distance is the number of positions at which the corresponding symbols are different. - * It is used in information theory, coding theory, and computer science. - *

+ * Hamming distance (consolidated implementation). + * + *

Resolves duplicate implementations: single class for Hamming distance over strings, + * integers, and binary strings. Previously duplicated in strings, bitmanipulation, and others.cn. + * + *

The Hamming distance is the number of positions at which the corresponding symbols differ. + * * @see Hamming distance - Wikipedia */ public final class HammingDistance { @@ -14,27 +16,20 @@ private HammingDistance() { /** * Calculates the Hamming distance between two strings of equal length. - *

- * The Hamming distance is defined only for strings of equal length. If the strings are not - * of equal length, this method throws an {@code IllegalArgumentException}. - *

* * @param s1 the first string * @param s2 the second string - * @return the Hamming distance between the two strings - * @throws IllegalArgumentException if the lengths of {@code s1} and {@code s2} are not equal + * @return the number of positions where the characters differ + * @throws IllegalArgumentException if either string is null or lengths differ */ public static int calculateHammingDistance(String s1, String s2) { if (s1 == null || s2 == null) { throw new IllegalArgumentException("Strings must not be null"); } - if (s1.length() != s2.length()) { throw new IllegalArgumentException("String lengths must be equal"); } - int distance = 0; - for (int i = 0; i < s1.length(); i++) { if (s1.charAt(i) != s2.charAt(i)) { distance++; @@ -42,4 +37,47 @@ public static int calculateHammingDistance(String s1, String s2) { } return distance; } + + /** + * Calculates the Hamming distance between two integers (number of differing bits). + * + * @param x the first integer + * @param y the second integer + * @return the number of bit positions where the two integers differ + */ + public static int hammingDistance(int x, int y) { + return Integer.bitCount(x ^ y); + } + + /** + * Computes the Hamming distance between two binary strings (only '0' and '1' allowed). + * + * @param bitsStrA first binary string + * @param bitsStrB second binary string (must have same length as bitsStrA) + * @return the number of positions where the two binary strings differ + * @throws IllegalArgumentException if lengths differ or any character is not '0' or '1' + */ + public static int computeBinary(String bitsStrA, String bitsStrB) { + if (bitsStrA == null || bitsStrB == null) { + throw new IllegalArgumentException("Input strings must not be null"); + } + if (bitsStrA.length() != bitsStrB.length()) { + throw new IllegalArgumentException("Input strings must have the same length."); + } + int distance = 0; + for (int i = 0; i < bitsStrA.length(); i++) { + char a = bitsStrA.charAt(i); + char b = bitsStrB.charAt(i); + if (a != '0' && a != '1') { + throw new IllegalArgumentException("Input must be a binary string."); + } + if (b != '0' && b != '1') { + throw new IllegalArgumentException("Input must be a binary string."); + } + if (a != b) { + distance++; + } + } + return distance; + } } diff --git a/src/main/java/com/thealgorithms/strings/LongestPalindromicSubstring.java b/src/main/java/com/thealgorithms/strings/LongestPalindromicSubstring.java index ca500357ba77..14bce4693782 100644 --- a/src/main/java/com/thealgorithms/strings/LongestPalindromicSubstring.java +++ b/src/main/java/com/thealgorithms/strings/LongestPalindromicSubstring.java @@ -1,14 +1,26 @@ package com.thealgorithms.strings; -final class LongestPalindromicSubstring { +/** + * Longest Palindromic Substring (consolidated implementation). + * + *

Resolves duplicate implementations: single class providing both a brute-force and a + * dynamic-programming solution. Previously duplicated in strings and dynamicprogramming packages. + * + *

A palindromic substring reads the same backward as forward. This class offers: + *

+ */ +public final class LongestPalindromicSubstring { private LongestPalindromicSubstring() { } /** - * Finds the longest palindromic substring in the given string. + * Finds the longest palindromic substring using brute force (check every substring). * * @param s the input string - * @return the longest palindromic substring + * @return the longest palindromic substring, or "" if null or empty */ public static String longestPalindrome(String s) { if (s == null || s.isEmpty()) { @@ -17,7 +29,7 @@ public static String longestPalindrome(String s) { String maxStr = ""; for (int i = 0; i < s.length(); ++i) { for (int j = i; j < s.length(); ++j) { - if (isValid(s, i, j) && (j - i + 1 > maxStr.length())) { + if (isPalindrome(s, i, j) && (j - i + 1 > maxStr.length())) { maxStr = s.substring(i, j + 1); } } @@ -25,9 +37,44 @@ public static String longestPalindrome(String s) { return maxStr; } - private static boolean isValid(String s, int lo, int hi) { - int n = hi - lo + 1; - for (int i = 0; i < n / 2; ++i) { + /** + * Finds the longest palindromic substring using dynamic programming. + * Fills a table for all substring lengths; returns the longest palindrome found. + * + * @param input the input string + * @return the longest palindromic substring, or the input if null/empty + */ + public static String lps(String input) { + if (input == null || input.isEmpty()) { + return input; + } + int n = input.length(); + boolean[][] dp = new boolean[n][n]; + int start = 0; + int end = 0; + + // g = gap (length of substring - 1); i, j = left and right indices + for (int g = 0; g < n; g++) { + for (int i = 0, j = g; j < n; i++, j++) { + if (g == 0) { + dp[i][j] = true; + } else if (g == 1) { + dp[i][j] = input.charAt(i) == input.charAt(j); + } else { + dp[i][j] = input.charAt(i) == input.charAt(j) && dp[i + 1][j - 1]; + } + if (dp[i][j]) { + start = i; + end = j; + } + } + } + return input.substring(start, end + 1); + } + + private static boolean isPalindrome(String s, int lo, int hi) { + int len = hi - lo + 1; + for (int i = 0; i < len / 2; i++) { if (s.charAt(lo + i) != s.charAt(hi - i)) { return false; } diff --git a/src/main/java/com/thealgorithms/strings/ValidParentheses.java b/src/main/java/com/thealgorithms/strings/ValidParentheses.java deleted file mode 100644 index 25a72f379dec..000000000000 --- a/src/main/java/com/thealgorithms/strings/ValidParentheses.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.thealgorithms.strings; - -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.Map; - -/** - * Validates if a given string has valid matching parentheses. - *

- * A string is considered valid if: - *

- * - * Allowed characters: '(', ')', '{', '}', '[', ']' - */ -public final class ValidParentheses { - private ValidParentheses() { - } - - private static final Map BRACKET_PAIRS = Map.of(')', '(', '}', '{', ']', '['); - - /** - * Checks if the input string has valid parentheses. - * - * @param s the string containing only bracket characters - * @return true if valid, false otherwise - * @throws IllegalArgumentException if the string contains invalid characters or is null - */ - public static boolean isValid(String s) { - if (s == null) { - throw new IllegalArgumentException("Input string cannot be null"); - } - - Deque stack = new ArrayDeque<>(); - - for (char c : s.toCharArray()) { - if (BRACKET_PAIRS.containsValue(c)) { - stack.push(c); // opening bracket - } else if (BRACKET_PAIRS.containsKey(c)) { - if (stack.isEmpty() || stack.pop() != BRACKET_PAIRS.get(c)) { - return false; - } - } else { - throw new IllegalArgumentException("Unexpected character: " + c); - } - } - - return stack.isEmpty(); - } -} diff --git a/src/test/java/com/thealgorithms/bitmanipulation/HammingDistanceTest.java b/src/test/java/com/thealgorithms/bitmanipulation/HammingDistanceTest.java index bde39a69f190..393397c26fdc 100644 --- a/src/test/java/com/thealgorithms/bitmanipulation/HammingDistanceTest.java +++ b/src/test/java/com/thealgorithms/bitmanipulation/HammingDistanceTest.java @@ -2,6 +2,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; +import com.thealgorithms.strings.HammingDistance; import org.junit.jupiter.api.Test; public class HammingDistanceTest { diff --git a/src/test/java/com/thealgorithms/dynamicprogramming/LongestPalindromicSubstringTest.java b/src/test/java/com/thealgorithms/dynamicprogramming/LongestPalindromicSubstringTest.java index 278de7e10e0a..230f468ac279 100644 --- a/src/test/java/com/thealgorithms/dynamicprogramming/LongestPalindromicSubstringTest.java +++ b/src/test/java/com/thealgorithms/dynamicprogramming/LongestPalindromicSubstringTest.java @@ -2,6 +2,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; +import com.thealgorithms.strings.LongestPalindromicSubstring; import java.util.stream.Stream; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; diff --git a/src/test/java/com/thealgorithms/greedyalgorithms/CoinChangeTest.java b/src/test/java/com/thealgorithms/greedyalgorithms/CoinChangeTest.java index b9745be63088..465e76aef02c 100644 --- a/src/test/java/com/thealgorithms/greedyalgorithms/CoinChangeTest.java +++ b/src/test/java/com/thealgorithms/greedyalgorithms/CoinChangeTest.java @@ -12,49 +12,49 @@ public class CoinChangeTest { @Test public void testCoinChangeProblemWithValidAmount() { ArrayList expected = new ArrayList<>(Arrays.asList(500, 50, 20, 20, 1)); - ArrayList coins = CoinChange.coinChangeProblem(591); + ArrayList coins = GreedyCoinChange.coinChangeProblem(591); assertEquals(expected, coins); } @Test public void testCoinChangeProblemWithLargeAmount() { List expected = singletonList(2000); - ArrayList coins = CoinChange.coinChangeProblem(2000); + ArrayList coins = GreedyCoinChange.coinChangeProblem(2000); assertEquals(expected, coins); } @Test public void testCoinChangeProblemWithPartialCoins2() { ArrayList expected = new ArrayList<>(Arrays.asList(500, 50, 20)); - ArrayList coins = CoinChange.coinChangeProblem(570); + ArrayList coins = GreedyCoinChange.coinChangeProblem(570); assertEquals(expected, coins); } @Test public void testCoinChangeProblemWithSmallAmount() { ArrayList expected = new ArrayList<>(Arrays.asList(2, 1)); - ArrayList coins = CoinChange.coinChangeProblem(3); + ArrayList coins = GreedyCoinChange.coinChangeProblem(3); assertEquals(expected, coins); } @Test public void testCoinChangeProblemWithLargeAmountAndMultipleDenominations() { ArrayList expected = new ArrayList<>(Arrays.asList(2000, 2000, 2000, 2000, 500, 500, 500, 100, 100, 100, 100, 50, 20, 20, 5, 2, 2)); - ArrayList coins = CoinChange.coinChangeProblem(9999); + ArrayList coins = GreedyCoinChange.coinChangeProblem(9999); assertEquals(expected, coins); } @Test public void testCoinChangeProblemWithAllDenominations() { ArrayList expected = new ArrayList<>(Arrays.asList(2000, 500, 100, 100, 100, 50, 20, 10, 5, 2, 1)); - ArrayList coins = CoinChange.coinChangeProblem(2888); + ArrayList coins = GreedyCoinChange.coinChangeProblem(2888); assertEquals(expected, coins); } @Test public void testCoinChangeProblemWithZeroAmount() { ArrayList expected = new ArrayList<>(); - ArrayList coins = CoinChange.coinChangeProblem(0); + ArrayList coins = GreedyCoinChange.coinChangeProblem(0); assertEquals(expected, coins); } } diff --git a/src/test/java/com/thealgorithms/others/BoyerMooreTest.java b/src/test/java/com/thealgorithms/others/BoyerMooreTest.java index 8416535b2111..cef206259f03 100644 --- a/src/test/java/com/thealgorithms/others/BoyerMooreTest.java +++ b/src/test/java/com/thealgorithms/others/BoyerMooreTest.java @@ -11,7 +11,7 @@ public class BoyerMooreTest { @ParameterizedTest @MethodSource("inputStreamWithExistingMajority") void checkWhenMajorityExists(int expected, int[] input) { - Assertions.assertEquals(expected, BoyerMoore.findMajorityElement(input).get()); + Assertions.assertEquals(expected, BoyerMooreMajorityVote.findMajorityElement(input).get()); } private static Stream inputStreamWithExistingMajority() { @@ -21,7 +21,7 @@ private static Stream inputStreamWithExistingMajority() { @ParameterizedTest @MethodSource("inputStreamWithoutMajority") void checkWhenMajorityExists(int[] input) { - Assertions.assertFalse(BoyerMoore.findMajorityElement(input).isPresent()); + Assertions.assertFalse(BoyerMooreMajorityVote.findMajorityElement(input).isPresent()); } private static Stream inputStreamWithoutMajority() { diff --git a/src/test/java/com/thealgorithms/others/cn/HammingDistanceTest.java b/src/test/java/com/thealgorithms/others/cn/HammingDistanceTest.java index 669f928cd247..f32b77447d98 100644 --- a/src/test/java/com/thealgorithms/others/cn/HammingDistanceTest.java +++ b/src/test/java/com/thealgorithms/others/cn/HammingDistanceTest.java @@ -1,12 +1,13 @@ package com.thealgorithms.others.cn; +import com.thealgorithms.strings.HammingDistance; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; public class HammingDistanceTest { @Test public void checkForDifferentBits() { - int answer = HammingDistance.compute("000", "011"); + int answer = HammingDistance.computeBinary("000", "011"); Assertions.assertThat(answer).isEqualTo(2); } @@ -21,33 +22,33 @@ public void checkForDifferentBits() { */ @Test public void checkForDifferentBitsLength() { - int answer = HammingDistance.compute("10101", "11110"); + int answer = HammingDistance.computeBinary("10101", "11110"); Assertions.assertThat(answer).isEqualTo(3); } @Test public void checkForSameBits() { String someBits = "111"; - int answer = HammingDistance.compute(someBits, someBits); + int answer = HammingDistance.computeBinary(someBits, someBits); Assertions.assertThat(answer).isEqualTo(0); } @Test public void checkForLongDataBits() { - int answer = HammingDistance.compute("10010101101010000100110100", "00110100001011001100110101"); + int answer = HammingDistance.computeBinary("10010101101010000100110100", "00110100001011001100110101"); Assertions.assertThat(answer).isEqualTo(7); } @Test public void mismatchDataBits() { - Exception ex = org.junit.jupiter.api.Assertions.assertThrows(IllegalArgumentException.class, () -> { HammingDistance.compute("100010", "00011"); }); + Exception ex = org.junit.jupiter.api.Assertions.assertThrows(IllegalArgumentException.class, () -> { HammingDistance.computeBinary("100010", "00011"); }); Assertions.assertThat(ex.getMessage()).contains("must have the same length"); } @Test public void mismatchDataBits2() { - Exception ex = org.junit.jupiter.api.Assertions.assertThrows(IllegalArgumentException.class, () -> { HammingDistance.compute("1", "11"); }); + Exception ex = org.junit.jupiter.api.Assertions.assertThrows(IllegalArgumentException.class, () -> { HammingDistance.computeBinary("1", "11"); }); Assertions.assertThat(ex.getMessage()).contains("must have the same length"); } @@ -55,27 +56,27 @@ public void mismatchDataBits2() { @Test public void checkForLongDataBitsSame() { String someBits = "10010101101010000100110100"; - int answer = HammingDistance.compute(someBits, someBits); + int answer = HammingDistance.computeBinary(someBits, someBits); Assertions.assertThat(answer).isEqualTo(0); } @Test public void checkForEmptyInput() { String someBits = ""; - int answer = HammingDistance.compute(someBits, someBits); + int answer = HammingDistance.computeBinary(someBits, someBits); Assertions.assertThat(answer).isEqualTo(0); } @Test public void checkForInputOfLength1() { String someBits = "0"; - int answer = HammingDistance.compute(someBits, someBits); + int answer = HammingDistance.computeBinary(someBits, someBits); Assertions.assertThat(answer).isEqualTo(0); } @Test public void computeThrowsExceptionWhenInputsAreNotBitStrs() { - Exception ex = org.junit.jupiter.api.Assertions.assertThrows(IllegalArgumentException.class, () -> { HammingDistance.compute("1A", "11"); }); + Exception ex = org.junit.jupiter.api.Assertions.assertThrows(IllegalArgumentException.class, () -> { HammingDistance.computeBinary("1A", "11"); }); Assertions.assertThat(ex.getMessage()).contains("must be a binary string"); } diff --git a/src/test/java/com/thealgorithms/strings/ValidParenthesesTest.java b/src/test/java/com/thealgorithms/strings/ValidParenthesesTest.java index 411b11e743b8..916a96f4326b 100644 --- a/src/test/java/com/thealgorithms/strings/ValidParenthesesTest.java +++ b/src/test/java/com/thealgorithms/strings/ValidParenthesesTest.java @@ -1,33 +1,52 @@ package com.thealgorithms.strings; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +import com.thealgorithms.stacks.ValidParentheses; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; +/** + * Tests for ValidParentheses (consolidated implementation in stacks package). + */ public class ValidParenthesesTest { @ParameterizedTest(name = "Input: \"{0}\" β†’ Expected: {1}") - @CsvSource({"'()', true", "'()[]{}', true", "'(]', false", "'{[]}', true", "'([{}])', true", "'([)]', false", "'', true", "'(', false", "')', false", "'{{{{}}}}', true", "'[({})]', true", "'[(])', false", "'[', false", "']', false", "'()()()()', true", "'(()', false", "'())', false", - "'{[()()]()}', true"}) - void - testIsValid(String input, boolean expected) { + @CsvSource({ + "'()', true", + "'()[]{}', true", + "'(]', false", + "'{[]}', true", + "'([{}])', true", + "'([)]', false", + "'', true", + "'(', false", + "')', false", + "'{{{{}}}}', true", + "'[({})]', true", + "'[(])', false", + "'[', false", + "']', false", + "'()()()()', true", + "'(()', false", + "'())', false", + "'{[()()]()}', true" + }) + void testIsValid(String input, boolean expected) { assertEquals(expected, ValidParentheses.isValid(input)); } @Test - void testNullInputThrows() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> ValidParentheses.isValid(null)); - assertEquals("Input string cannot be null", ex.getMessage()); + void testNullInputReturnsFalse() { + assertFalse(ValidParentheses.isValid(null)); } - @ParameterizedTest(name = "Input: \"{0}\" β†’ throws IllegalArgumentException") + @ParameterizedTest(name = "Input: \"{0}\" β†’ invalid characters return false") @CsvSource({"'a'", "'()a'", "'[123]'", "'{hello}'", "'( )'", "'\t'", "'\n'", "'@#$%'"}) - void testInvalidCharactersThrow(String input) { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> ValidParentheses.isValid(input)); - assertTrue(ex.getMessage().startsWith("Unexpected character")); + void testInvalidCharactersReturnFalse(String input) { + assertFalse(ValidParentheses.isValid(input)); } }