Skip to content

Commit 2f6aed6

Browse files
authored
Merge branch 'master' into refactor/HammingDistance
2 parents d445810 + d810a1d commit 2f6aed6

File tree

7 files changed

+176
-57
lines changed

7 files changed

+176
-57
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
* @yanglbme @vil02 @BamaCharanChhandogi @alxkm
1+
* @yanglbme @vil02 @BamaCharanChhandogi @alxkm @siriak

src/main/java/com/thealgorithms/dynamicprogramming/RegexMatching.java

Lines changed: 56 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,28 @@
66
* cover the entire text ?-> matches single characters *-> match the sequence of
77
* characters
88
*
9-
* For calculation of Time and Space Complexity. Let N be length of src and M be
10-
* length of pat
9+
* For calculation of Time and Space Complexity. Let N be length of src and M be length of pat
1110
*
11+
* Memoization vs Tabulation : https://www.geeksforgeeks.org/tabulation-vs-memoization/
12+
* Question Link : https://practice.geeksforgeeks.org/problems/wildcard-pattern-matching/1
1213
*/
1314
public final class RegexMatching {
1415
private RegexMatching() {
1516
}
1617

17-
// Method 1: Using Recursion
18-
// Time Complexity=0(2^(N+M)) Space Complexity=Recursion Extra Space
19-
static boolean regexRecursion(String src, String pat) {
18+
/**
19+
* Method 1: Determines if the given source string matches the given pattern using a recursive approach.
20+
* This method directly applies recursion to check if the source string matches the pattern, considering
21+
* the wildcards '?' and '*'.
22+
*
23+
* Time Complexity: O(2^(N+M)), where N is the length of the source string and M is the length of the pattern.
24+
* Space Complexity: O(N + M) due to the recursion stack.
25+
*
26+
* @param src The source string to be matched against the pattern.
27+
* @param pat The pattern containing wildcards ('*' matches a sequence of characters, '?' matches a single character).
28+
* @return {@code true} if the source string matches the pattern, {@code false} otherwise.
29+
*/
30+
public static boolean regexRecursion(String src, String pat) {
2031
if (src.length() == 0 && pat.length() == 0) {
2132
return true;
2233
}
@@ -50,8 +61,19 @@ static boolean regexRecursion(String src, String pat) {
5061
return ans;
5162
}
5263

53-
// Method 2: Using Recursion and breaking string using virtual index
54-
// Time Complexity=0(2^(N+M)) Space Complexity=Recursion Extra Space
64+
/**
65+
* Method 2: Determines if the given source string matches the given pattern using recursion.
66+
* This method utilizes a virtual index for both the source string and the pattern to manage the recursion.
67+
*
68+
* Time Complexity: O(2^(N+M)) where N is the length of the source string and M is the length of the pattern.
69+
* Space Complexity: O(N + M) due to the recursion stack.
70+
*
71+
* @param src The source string to be matched against the pattern.
72+
* @param pat The pattern containing wildcards ('*' matches a sequence of characters, '?' matches a single character).
73+
* @param svidx The current index in the source string.
74+
* @param pvidx The current index in the pattern.
75+
* @return {@code true} if the source string matches the pattern, {@code false} otherwise.
76+
*/
5577
static boolean regexRecursion(String src, String pat, int svidx, int pvidx) {
5678
if (src.length() == svidx && pat.length() == pvidx) {
5779
return true;
@@ -83,9 +105,21 @@ static boolean regexRecursion(String src, String pat, int svidx, int pvidx) {
83105
return ans;
84106
}
85107

86-
// Method 3: Top-Down DP(Memoization)
87-
// Time Complexity=0(N*M) Space Complexity=0(N*M)+Recursion Extra Space
88-
static boolean regexRecursion(String src, String pat, int svidx, int pvidx, int[][] strg) {
108+
/**
109+
* Method 3: Determines if the given source string matches the given pattern using top-down dynamic programming (memoization).
110+
* This method utilizes memoization to store intermediate results, reducing redundant computations and improving efficiency.
111+
*
112+
* Time Complexity: O(N * M), where N is the length of the source string and M is the length of the pattern.
113+
* Space Complexity: O(N * M) for the memoization table, plus additional space for the recursion stack.
114+
*
115+
* @param src The source string to be matched against the pattern.
116+
* @param pat The pattern containing wildcards ('*' matches a sequence of characters, '?' matches a single character).
117+
* @param svidx The current index in the source string.
118+
* @param pvidx The current index in the pattern.
119+
* @param strg A 2D array used for memoization to store the results of subproblems.
120+
* @return {@code true} if the source string matches the pattern, {@code false} otherwise.
121+
*/
122+
public static boolean regexRecursion(String src, String pat, int svidx, int pvidx, int[][] strg) {
89123
if (src.length() == svidx && pat.length() == pvidx) {
90124
return true;
91125
}
@@ -120,8 +154,18 @@ static boolean regexRecursion(String src, String pat, int svidx, int pvidx, int[
120154
return ans;
121155
}
122156

123-
// Method 4: Bottom-Up DP(Tabulation)
124-
// Time Complexity=0(N*M) Space Complexity=0(N*M)
157+
/**
158+
* Method 4: Determines if the given source string matches the given pattern using bottom-up dynamic programming (tabulation).
159+
* This method builds a solution iteratively by filling out a table, where each cell represents whether a substring
160+
* of the source string matches a substring of the pattern.
161+
*
162+
* Time Complexity: O(N * M), where N is the length of the source string and M is the length of the pattern.
163+
* Space Complexity: O(N * M) for the table used in the tabulation process.
164+
*
165+
* @param src The source string to be matched against the pattern.
166+
* @param pat The pattern containing wildcards ('*' matches a sequence of characters, '?' matches a single character).
167+
* @return {@code true} if the source string matches the pattern, {@code false} otherwise.
168+
*/
125169
static boolean regexBU(String src, String pat) {
126170
boolean[][] strg = new boolean[src.length() + 1][pat.length() + 1];
127171
strg[src.length()][pat.length()] = true;
@@ -153,15 +197,4 @@ static boolean regexBU(String src, String pat) {
153197
}
154198
return strg[0][0];
155199
}
156-
157-
public static void main(String[] args) {
158-
String src = "aa";
159-
String pat = "*";
160-
System.out.println("Method 1: " + regexRecursion(src, pat));
161-
System.out.println("Method 2: " + regexRecursion(src, pat, 0, 0));
162-
System.out.println("Method 3: " + regexRecursion(src, pat, 0, 0, new int[src.length()][pat.length()]));
163-
System.out.println("Method 4: " + regexBU(src, pat));
164-
}
165200
}
166-
// Memoization vs Tabulation : https://www.geeksforgeeks.org/tabulation-vs-memoization/
167-
// Question Link : https://practice.geeksforgeeks.org/problems/wildcard-pattern-matching/1

src/main/java/com/thealgorithms/stacks/InfixToPostfix.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
11
package com.thealgorithms.stacks;
22

33
import java.util.Stack;
4+
import java.util.regex.Matcher;
5+
import java.util.regex.Pattern;
46

57
public final class InfixToPostfix {
68
private InfixToPostfix() {
79
}
810

9-
public static void main(String[] args) throws Exception {
10-
assert "32+".equals(infix2PostFix("3+2"));
11-
assert "123++".equals(infix2PostFix("1+(2+3)"));
12-
assert "34+5*6-".equals(infix2PostFix("(3+4)*5-6"));
13-
}
14-
1511
public static String infix2PostFix(String infixExpression) throws Exception {
16-
if (!BalancedBrackets.isBalanced(infixExpression)) {
12+
if (!BalancedBrackets.isBalanced(filterBrackets(infixExpression))) {
1713
throw new Exception("invalid expression");
1814
}
1915
StringBuilder output = new StringBuilder();
@@ -55,4 +51,10 @@ private static int precedence(char operator) {
5551
return -1;
5652
}
5753
}
54+
55+
private static String filterBrackets(String input) {
56+
Pattern pattern = Pattern.compile("[^(){}\\[\\]<>]");
57+
Matcher matcher = pattern.matcher(input);
58+
return matcher.replaceAll("");
59+
}
5860
}

src/main/java/com/thealgorithms/strings/LongestPalindromicSubstring.java

Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,31 @@
11
package com.thealgorithms.strings;
22

3-
// Longest Palindromic Substring
4-
import java.util.Scanner;
5-
63
final class LongestPalindromicSubstring {
74
private LongestPalindromicSubstring() {
85
}
96

10-
public static void main(String[] args) {
11-
Solution s = new Solution();
12-
String str = "";
13-
Scanner sc = new Scanner(System.in);
14-
System.out.print("Enter the string: ");
15-
str = sc.nextLine();
16-
System.out.println("Longest substring is : " + s.longestPalindrome(str));
17-
sc.close();
18-
}
19-
}
20-
21-
class Solution {
22-
23-
public String longestPalindrome(String s) {
24-
if (s == null || s.length() == 0) {
7+
/**
8+
* Finds the longest palindromic substring in the given string.
9+
*
10+
* @param s the input string
11+
* @return the longest palindromic substring
12+
*/
13+
public static String longestPalindrome(String s) {
14+
if (s == null || s.isEmpty()) {
2515
return "";
2616
}
27-
int n = s.length();
2817
String maxStr = "";
29-
for (int i = 0; i < n; ++i) {
30-
for (int j = i; j < n; ++j) {
31-
if (isValid(s, i, j)) {
32-
if (j - i + 1 > maxStr.length()) { // update maxStr
33-
maxStr = s.substring(i, j + 1);
34-
}
18+
for (int i = 0; i < s.length(); ++i) {
19+
for (int j = i; j < s.length(); ++j) {
20+
if (isValid(s, i, j) && (j - i + 1 > maxStr.length())) {
21+
maxStr = s.substring(i, j + 1);
3522
}
3623
}
3724
}
3825
return maxStr;
3926
}
4027

41-
private boolean isValid(String s, int lo, int hi) {
28+
private static boolean isValid(String s, int lo, int hi) {
4229
int n = hi - lo + 1;
4330
for (int i = 0; i < n / 2; ++i) {
4431
if (s.charAt(lo + i) != s.charAt(hi - i)) {
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package com.thealgorithms.dynamicprogramming;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
5+
import java.util.stream.Stream;
6+
import org.junit.jupiter.params.ParameterizedTest;
7+
import org.junit.jupiter.params.provider.Arguments;
8+
import org.junit.jupiter.params.provider.MethodSource;
9+
10+
public class RegexMatchingTest {
11+
12+
private record RegexTestCase(String s, String p, boolean expected) {
13+
}
14+
15+
private static Stream<Arguments> provideTestCases() {
16+
return Stream.of(Arguments.of(new RegexTestCase("aa", "*", true)), Arguments.of(new RegexTestCase("aa", "a*", true)), Arguments.of(new RegexTestCase("aa", "a", false)), Arguments.of(new RegexTestCase("cb", "?b", true)), Arguments.of(new RegexTestCase("cb", "?a", false)),
17+
Arguments.of(new RegexTestCase("adceb", "*a*b", true)), Arguments.of(new RegexTestCase("acdcb", "a*c?b", false)), Arguments.of(new RegexTestCase("", "*", true)), Arguments.of(new RegexTestCase("", "", true)));
18+
}
19+
20+
@ParameterizedTest
21+
@MethodSource("provideTestCases")
22+
void testRegexRecursionMethod1(RegexTestCase testCase) {
23+
assertEquals(testCase.expected(), RegexMatching.regexRecursion(testCase.s(), testCase.p()));
24+
}
25+
26+
@ParameterizedTest
27+
@MethodSource("provideTestCases")
28+
void testRegexRecursionMethod2(RegexTestCase testCase) {
29+
assertEquals(testCase.expected(), RegexMatching.regexRecursion(testCase.s(), testCase.p(), 0, 0));
30+
}
31+
32+
@ParameterizedTest
33+
@MethodSource("provideTestCases")
34+
void testRegexRecursionMethod3(RegexTestCase testCase) {
35+
assertEquals(testCase.expected(), RegexMatching.regexRecursion(testCase.s(), testCase.p(), 0, 0, new int[testCase.s().length()][testCase.p().length()]));
36+
}
37+
38+
@ParameterizedTest
39+
@MethodSource("provideTestCases")
40+
void testRegexBottomUp(RegexTestCase testCase) {
41+
assertEquals(testCase.expected(), RegexMatching.regexBU(testCase.s(), testCase.p()));
42+
}
43+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.thealgorithms.stacks;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertThrows;
5+
6+
import java.util.stream.Stream;
7+
import org.junit.jupiter.params.ParameterizedTest;
8+
import org.junit.jupiter.params.provider.Arguments;
9+
import org.junit.jupiter.params.provider.MethodSource;
10+
11+
class InfixToPostfixTest {
12+
13+
@ParameterizedTest
14+
@MethodSource("provideValidExpressions")
15+
void testValidExpressions(String infix, String expectedPostfix) throws Exception {
16+
assertEquals(expectedPostfix, InfixToPostfix.infix2PostFix(infix));
17+
}
18+
19+
private static Stream<Arguments> provideValidExpressions() {
20+
return Stream.of(Arguments.of("3+2", "32+"), Arguments.of("1+(2+3)", "123++"), Arguments.of("(3+4)*5-6", "34+5*6-"));
21+
}
22+
23+
@ParameterizedTest
24+
@MethodSource("provideInvalidExpressions")
25+
void testInvalidExpressions(String infix, String expectedMessage) {
26+
Exception exception = assertThrows(Exception.class, () -> InfixToPostfix.infix2PostFix(infix));
27+
assertEquals(expectedMessage, exception.getMessage());
28+
}
29+
30+
private static Stream<Arguments> provideInvalidExpressions() {
31+
return Stream.of(Arguments.of("((a+b)*c-d", "invalid expression"));
32+
}
33+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.thealgorithms.strings;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
5+
import java.util.stream.Stream;
6+
import org.junit.jupiter.params.ParameterizedTest;
7+
import org.junit.jupiter.params.provider.Arguments;
8+
import org.junit.jupiter.params.provider.MethodSource;
9+
10+
class LongestPalindromicSubstringTest {
11+
12+
@ParameterizedTest
13+
@MethodSource("provideTestCasesForLongestPalindrome")
14+
void testLongestPalindrome(String input, String expected) {
15+
assertEquals(expected, LongestPalindromicSubstring.longestPalindrome(input));
16+
}
17+
18+
private static Stream<Arguments> provideTestCasesForLongestPalindrome() {
19+
return Stream.of(Arguments.of("babad", "bab"), Arguments.of("cbbd", "bb"), Arguments.of("a", "a"), Arguments.of("", ""), Arguments.of("abc", "a"), Arguments.of(null, ""), Arguments.of("aaaaa", "aaaaa"));
20+
}
21+
}

0 commit comments

Comments
 (0)