1. Problem Statement
Given strings S and T, find the minimum (contiguous) substring W of S, such that T is a subsequence of W.
If there is no such window in S that contains all characters in T after keeping the order of characters in T, return an empty string "". If there are multiple such windows of the same minimum length, return the one with the smallest starting index.
Input: S = "abcdebdde", T = "bde"
Output: "bcde" (Not "bdde", as "bcde" appears earlier)
2. Approach: Sliding Window + Reverse Verification
Standard sliding window doesn't work directly because we need to maintain order. We use a two-pass optimization for every potential window.
- Find a Valid Window:
- Iterate through
Swith a pointeri. - Maintain a pointer
jforT. - If
S[i] == T[j], incrementj. - When
jreaches the end ofT, we found a potential window ending ati.
- Iterate through
- Optimize the Start:
- We know the window ends at
i. But where should it start to be as small as possible? - Move backward from
ito find the last occurrence of each character ofTin reverse order. - This gives us the optimal (latest) start index for the current end index.
- We know the window ends at
- Update: Record the smallest window and reset
jto 0. Restart the search fromstart + 1.
3. Java Implementation
public String minWindow(String S, String T) {
char[] s = S.toCharArray(), t = T.toCharArray();
int i = 0, j = 0;
int minLen = Integer.MAX_VALUE;
String res = "";
while (i < s.length) {
if (s[i] == t[j]) {
j++;
// Found a valid window
if (j == t.length) {
int end = i;
j--;
// Pass 2: Shrink from right to left to find optimal start
while (j >= 0) {
if (s[i] == t[j]) j--;
i--;
}
i++; // Pushed back to the start index
j++; // Reset j to 0 for next search
if (end - i + 1 < minLen) {
minLen = end - i + 1;
res = S.substring(i, end + 1);
}
// Important: Jump back to start + 1 to find the next potential window
i = i + 1;
j = 0;
}
}
i++;
}
return res;
}
4. 5-Minute "Video-Style" Walkthrough
- The "Aha!" Moment: If you find "b...d...e", you've found a window. But the "b" you found at the start might not be the best "b". There might be another "b" much closer to the "d".
- The Reverse Pass: By walking backward from the "e" we just found, we guarantee we find the latest possible "d" and "b" that still form the sequence. This "squeeze" from both sides ensures the window is as small as possible.
- The Index Jump: After finding a window, don't just continue from
i. Jump back tostart + 1. This handles overlapping windows likeS="bbde", T="bde".
5. Interview Discussion
- Interviewer: "What is the time complexity?"
- You: "In the worst case, $O(S^2)$, but in practice, it is closer to $O(S)$ because we only perform the reverse pass when a full match is found."
- Interviewer: "Can we use DP?"
- You: "Yes! We can use a 2D array where
dp[i][j]is the starting index of the shortest substring ofS[0...j]that containsT[0...i]as a subsequence. This would be a strict $O(S \times T)$ solution."