Skip to content

Commit a60ade3

Browse files
committed
Update minimum window substring problem
1 parent 19ece3a commit a60ade3

File tree

6 files changed

+100
-67
lines changed

6 files changed

+100
-67
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ List of Programs related to data structures and algorithms
8484

8585
2. Longest repeating character replacement: [Source](https://github.com/sudheerj/datastructures-algorithms/blob/master/src/javascript/algorithms/strings/2.longestRepeatingCharReplacement/longestRepeatingCharReplacement.js) [JavaScript](https://livecodes.io/?console&x=https://github.com/sudheerj/datastructures-algorithms/blob/master/src/javascript/algorithms/strings/2.longestRepeatingCharReplacement/longestRepeatingCharReplacement.js) [Documentation](https://github.com/sudheerj/datastructures-algorithms/blob/master/src/javascript/algorithms/strings/2.longestRepeatingCharReplacement/longestRepeatingCharReplacement.md)
8686

87-
3. Minimum window substring: [JavaScript](https://livecodes.io/?console&x=https://github.com/sudheerj/datastructures-algorithms/blob/master/src/javascript/algorithms/strings/minWindowSubstring/minWindowSubstring.js) [Documentation](https://github.com/sudheerj/datastructures-algorithms/blob/master/src/javascript/algorithms/strings/minWindowSubstring/minWindowSubstring.md)
87+
3. Minimum window substring: [Source](https://github.com/sudheerj/datastructures-algorithms/blob/master/src/javascript/algorithms/strings/3.minWindowSubstring/minWindowSubstring.js) [JavaScript](https://livecodes.io/?console&x=https://github.com/sudheerj/datastructures-algorithms/blob/master/src/javascript/algorithms/strings/3.minWindowSubstring/minWindowSubstring.js) [Documentation](https://github.com/sudheerj/datastructures-algorithms/blob/master/src/javascript/algorithms/strings/3.minWindowSubstring/minWindowSubstring.md)
8888

8989
4. Valid anagram: [JavaScript](https://livecodes.io/?console&x=https://github.com/sudheerj/datastructures-algorithms/blob/master/src/javascript/algorithms/strings/validAnagram.js)
9090

src/java1/algorithms/strings/minWindowSubstring/MinWindowSubstring.java

+9-14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
package java1.algorithms.strings.minWindowSubstring;
2-
// Sliding window: TC: O(m) + O(n) SC: O(m) + O(n)
2+
// Sliding window: TC: O(m) + O(n), SC: O(m) + O(n)
33

44
import java.util.HashMap;
55

@@ -13,10 +13,9 @@ private static String minWindowSubstring(String windowStr, String subStr) {
1313
HashMap<Character, Integer> windowStrCount = new HashMap<>();
1414

1515
int minLength = Integer.MAX_VALUE;
16-
int leftIndex = -1, rightIndex = -1;
16+
int[] subStrBoundaries = new int[]{-1, -1};
1717

18-
for(int i=0; i< subStr.length(); i++) {
19-
char ch = subStr.charAt(i);
18+
for(char ch: subStr.toCharArray()) {
2019
subStrCount.put(ch, subStrCount.getOrDefault(ch, 0) + 1);
2120
}
2221

@@ -27,34 +26,30 @@ private static String minWindowSubstring(String windowStr, String subStr) {
2726

2827
if(subStrCount.containsKey(rightChar)) {
2928
windowStrCount.put(rightChar, windowStrCount.getOrDefault(rightChar, 0) + 1);
30-
if(subStrCount.get(rightChar).intValue() == windowStrCount.get(rightChar).intValue()) {
29+
if(subStrCount.get(rightChar) == windowStrCount.get(rightChar)) {
3130
having++;
3231
}
3332
}
3433

3534
while(required == having) {
3635
if(minLength > right-left+1) {
3736
minLength = right-left+1;
38-
leftIndex = left;
39-
rightIndex = right;
37+
subStrBoundaries[0] = left;
38+
subStrBoundaries[1] = right;
4039
}
40+
4141
char leftChar = windowStr.charAt(left);
42-
4342
if(subStrCount.containsKey(leftChar)) {
4443
windowStrCount.put(leftChar, windowStrCount.get(leftChar)-1);
45-
if(windowStrCount.get(leftChar).intValue() < subStrCount.get(leftChar).intValue()) {
44+
if(windowStrCount.get(leftChar) < subStrCount.get(leftChar)) {
4645
having--;
4746
}
4847
}
4948
left++;
5049
}
5150
}
52-
if(leftIndex == -1 || rightIndex == -1) {
53-
return "";
54-
} else {
55-
return windowStr.substring(leftIndex, rightIndex+1);
56-
}
5751

52+
return minLength == Integer.MAX_VALUE ? "" : windowStr.substring(subStrBoundaries[0], subStrBoundaries[1]+1);
5853
}
5954

6055
public static void main(String[] args) {
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,51 @@
1+
**Description:**
2+
Given two strings `str` and `subStr` of lengths `m` and `n` respectively, return the minimum window
3+
substring of `str` such that every character in `subStr` (including duplicates) is included in the window. If there is no such substring available, just return the empty string(i.e,"").
4+
5+
### Examples
6+
Example 1:
7+
8+
Input: str = "ADOBECODEBANC", subStr = "ABC"
9+
Output: "BANC"
10+
Explanation: The minimum window substring "BANC" includes 'A', 'B', and 'C' from string t.
11+
12+
Example 2:
13+
Input: str = "A", subStr = "A"
14+
Output: "A"
15+
16+
Example 3:
17+
Input: str = "a", subStr = "aa"
18+
Output: ""
19+
120
**Algorithmic Steps**
2-
This problem is solved with the help of sliding window approach using two hash maps. The algorithmic approach can be summarized as follows:
21+
This problem is solved with the help of **sliding window** approach using two hash maps. The algorithmic approach can be summarized as follows:
322

423
1. Add a preliminary corner case condition by checking the second substring is empty or not. If it is empty, then return the empty substring as minimum window substring.
524

6-
2. Initialize two HashMaps, which store unique characters and their respective character count for the given two substrings.
25+
2. Initialize two HashMaps(`windowStrCount` & `subStrCount`), which store unique characters and their respective character count for their given substrings.
726

8-
3. Initialize minLength variable to max integer value, to store the length of the minimum window substring.
27+
3. Initialize `minLength` variable with maximum integer value, which is used to store the length of the minimum window substring.
928

10-
4. Initialize left(leftIndex) and right(rightIndex) indexes to -1, to keep track of the minimum substring window boundaries.
29+
4. Initialize substring boundaries(`subStrBoudaries`) variable to [-1, -1], which is used to keep track of the minimum substring window boundaries.
1130

12-
5. Iterate over the second substring and count the character count using hashmap.
31+
5. Iterate over the second substring and count the character count using respective hashmap.
1332

14-
6. Initialize total character count(i.e, `required`) from second substring to max integer value and total character count(i.e, `having`) of first substring based on first substring to 0.
33+
6. Initialize second substring's required character count(i.e, `required`) to the size of second hashmap and total character count(i.e, `having`) of first substring to 0.
1534

1635
7. Initialize both left and right pointers to 0, to keep track of the current window substring.
1736

18-
8. Iterate through second substring using right pointer until the end of string.
37+
8. Iterate through first substring using right pointer until the end of string.
1938

20-
9. If the current character from first substring exists in second substring hashmap, update the character counter of first hashmap. Also, increment `having` variable if the character count in both hashmaps are equal.
39+
9. If the current character from first substring exists in second substring hashmap, update the character count of first hashmap. Also, increment `having` variable if the character count in both hashmaps are equal.
2140

22-
10. Until `required` and `having` variables are equal, first calculate the left and right indexes along with `minLength` variable. Thereafter, move/increment the left pointer and decrement the character count in first hashmap to find the minimum possible substring window. If the current left character found in second hashmap and first hashmap character count is less than second one, `having` variable needs to be decremented.
41+
10. Iterate a nested loop until `required` and `having` variables are equal. If the current substring's length is less than minimum substring's length which is calculated so far, just update `minLength` variable with current substring length and also the substring boundaries. Thereafter, shrink (or remove the left character) the substring window and decrement the character count in first hashmap. This logic is required to find the minimum possible substring window in the first string. If the current left character found in second hashmap and first hashmap character count is less than second one, `having` variable needs to be decremented.
2342

2443
11. Repeat steps 9-10 until the end of the first string.
2544

26-
7. If the leftIndex and rightIndex are still equals to -1, return empty string. Otherwise the substring based on leftIdex and rightIndex should be returned from first string.
45+
12. Return an empty string if the minimum substring length is not a maximum value. Otherwise return the substring of first string based on substring boundary index values.
2746

2847

2948
**Time and Space complexity:**
30-
This algorithm has a time complexity of `O(m) + O(n)`, where m and n represents lenghts of first and second strings. This is because we are traversing both the strings. Also, it requires space complexity of `O(m) + O(n)` due to two hashmaps used to store character count.
49+
This algorithm has a time complexity of `O(m) + O(n)`, where `m` and `n` represents lengths of first and second strings. This is because we are traversing both the strings.
50+
51+
Also, it requires space complexity of `O(m) + O(n)` due to two hashmaps used to store the character count.

src/javascript/algorithms/strings/minWindowSubstring/minWindowSubstring.js src/javascript/algorithms/strings/3.minWindowSubstring/minWindowSubstring.js

+7-11
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ function minWindowSubstring(windowStr, subStr) {
55
let subStrCount = new Map();
66

77
let minLength = Number.MAX_VALUE;
8-
let leftIndex = rightIndex = -1;
8+
let subStrboundaries = [-1, -1];
99

1010
for(const ch of subStr) {
1111
subStrCount.set(ch, (subStrCount.get(ch) || 0) + 1);
@@ -15,10 +15,10 @@ function minWindowSubstring(windowStr, subStr) {
1515
let left = 0;
1616

1717
for(let right = 0; right < windowStr.length; right++) {
18-
let rightChar = windowStr.charAt(right);
18+
let rightChar = windowStr[right];
1919

2020
if(subStrCount.has(rightChar)) {
21-
windowStrCount.set(rightChar, (windowStrCount.get(right) || 0) +1);
21+
windowStrCount.set(rightChar, (windowStrCount.get(rightChar) || 0) +1);
2222
if(subStrCount.get(rightChar) === windowStrCount.get(rightChar)) {
2323
having++;
2424
}
@@ -27,11 +27,11 @@ function minWindowSubstring(windowStr, subStr) {
2727
while(required === having) {
2828
if(minLength > right-left+1) {
2929
minLength = right-left+1;
30-
leftIndex = left;
31-
rightIndex = right;
30+
subStrboundaries[0] = left;
31+
subStrboundaries[1] = right;
3232
}
3333

34-
let leftChar = windowStr.charAt(left);
34+
let leftChar = windowStr[left];
3535
if(subStrCount.has(leftChar)) {
3636
windowStrCount.set(leftChar, windowStrCount.get(leftChar)-1);
3737
if(windowStrCount.get(leftChar) < subStrCount.get(leftChar)) {
@@ -41,12 +41,8 @@ function minWindowSubstring(windowStr, subStr) {
4141
left++;
4242
}
4343
}
44-
if(leftIndex === -1 || rightIndex === -1) {
45-
return "";
46-
} else {
47-
return windowStr.substring(leftIndex, rightIndex+1);
48-
}
4944

45+
return minLength === Number.MAX_VALUE ? "" : windowStr.substring(subStrboundaries[0], subStrboundaries[1]+1);
5046
}
5147

5248
let s1 ="ADOBECODEBANC", t1= "ABC";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
**Description:**
2+
Given two strings `str` and `subStr` of lengths `m` and `n` respectively, return the minimum window
3+
substring of `str` such that every character in `subStr` (including duplicates) is included in the window. If there is no such substring available, just return the empty string(i.e,"").
4+
5+
### Examples
6+
Example 1:
7+
8+
Input: str = "ADOBECODEBANC", subStr = "ABC"
9+
Output: "BANC"
10+
Explanation: The minimum window substring "BANC" includes 'A', 'B', and 'C' from string t.
11+
12+
Example 2:
13+
Input: str = "A", subStr = "A"
14+
Output: "A"
15+
16+
Example 3:
17+
Input: str = "a", subStr = "aa"
18+
Output: ""
19+
20+
**Algorithmic Steps**
21+
This problem is solved with the help of **sliding window** approach using two hash maps. The algorithmic approach can be summarized as follows:
22+
23+
1. Add a preliminary corner case condition by checking the second substring is empty or not. If it is empty, then return the empty substring as minimum window substring.
24+
25+
2. Initialize two HashMaps(`windowStrCount` & `subStrCount`), which store unique characters and their respective character count for their given substrings.
26+
27+
3. Initialize `minLength` variable with maximum integer value, which is used to store the length of the minimum window substring.
28+
29+
4. Initialize substring boundaries(`subStrBoudaries`) variable to [-1, -1], which is used to keep track of the minimum substring window boundaries.
30+
31+
5. Iterate over the second substring and count the character count using respective hashmap.
32+
33+
6. Initialize second substring's required character count(i.e, `required`) to the size of second hashmap and total character count(i.e, `having`) of first substring to 0.
34+
35+
7. Initialize both left and right pointers to 0, to keep track of the current window substring.
36+
37+
8. Iterate through first substring using right pointer until the end of string.
38+
39+
9. If the current character from first substring exists in second substring hashmap, update the character count of first hashmap. Also, increment `having` variable if the character count in both hashmaps are equal.
40+
41+
10. Iterate a nested loop until `required` and `having` variables are equal. If the current substring's length is less than minimum substring's length which is calculated so far, just update `minLength` variable with current substring length and also the substring boundaries. Thereafter, shrink (or remove the left character) the substring window and decrement the character count in first hashmap. This logic is required to find the minimum possible substring window in the first string. If the current left character found in second hashmap and first hashmap character count is less than second one, `having` variable needs to be decremented.
42+
43+
11. Repeat steps 9-10 until the end of the first string.
44+
45+
12. Return an empty string if the minimum substring length is not a maximum value. Otherwise return the substring of first string based on substring boundary index values.
46+
47+
48+
**Time and Space complexity:**
49+
This algorithm has a time complexity of `O(m) + O(n)`, where `m` and `n` represents lengths of first and second strings. This is because we are traversing both the strings.
50+
51+
Also, it requires space complexity of `O(m) + O(n)` due to two hashmaps used to store the character count.

src/javascript/algorithms/strings/minWindowSubstring/minWindowSubstring.md

-30
This file was deleted.

0 commit comments

Comments
 (0)