Minimum Window Substring in DSA Go - Time & Space Complexity
We want to understand how the time needed to find the smallest substring containing all characters grows as the input string gets longer.
How does the algorithm's work increase when the input size increases?
Analyze the time complexity of the following code snippet.
func minWindow(s string, t string) string {
need := map[byte]int{}
for i := 0; i < len(t); i++ {
need[t[i]]++
}
missing := len(t)
left := 0
start, end := 0, len(s)+1
for right := 0; right < len(s); right++ {
if need[s[right]] > 0 {
missing--
}
need[s[right]]--
for missing == 0 {
if right-left+1 < end-start {
start, end = left, right+1
}
need[s[left]]++
if need[s[left]] > 0 {
missing++
}
left++
}
}
if end <= len(s) {
return s[start:end]
}
return ""
}
This code finds the smallest substring in s that contains all characters of t.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The outer loop moves the
rightpointer over the strings. - Secondary operation: The inner loop moves the
leftpointer to shrink the window when all needed characters are found. - How many times: Each character in
sis visited at most twice: once byrightand once byleft.
As the input string s grows, the pointers move through it mostly once each.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 20 moves (each pointer moves through string) |
| 100 | About 200 moves |
| 1000 | About 2000 moves |
Pattern observation: The total work grows roughly in a straight line with input size, doubling because of two pointers moving.
Time Complexity: O(n + m)
This means the time grows linearly with the size of the input string s and the target string t.
[X] Wrong: "The inner loop makes this algorithm quadratic because it is nested inside the outer loop."
[OK] Correct: Each character is visited at most twice, so the total steps add up linearly, not multiplying to a square.
Understanding this sliding window approach and its time complexity shows you can handle efficient substring problems, a common skill interviewers look for.
"What if the target string t contains many repeated characters? How would that affect the time complexity?"
Practice
s and t?Solution
Step 1: Understand the problem goal
The problem asks to find the smallest part of stringsthat includes every character from stringtat least once.Step 2: Compare options with the problem goal
The smallest substring insthat contains all characters oftmatches the problem exactly. Other options describe different tasks unrelated to the minimum window substring.Final Answer:
The smallest substring in s that contains all characters of t -> Option CQuick Check:
Minimum window substring = smallest substring containing all chars [OK]
- Confusing minimum window with longest substring
- Thinking about counting occurrences instead of substring
- Ignoring the need to include all characters of t
Solution
Step 1: Identify the correct data structure for counting characters
We need a map with keys as characters (rune) and values as counts (int), somap[rune]intis correct.Step 2: Check each option's type
counts := make(map[rune]int) creates a map from rune to int, perfect for counting. Options B, C, and D use wrong types or slices, not suitable for counting characters.Final Answer:
counts := make(map[rune]int) -> Option BQuick Check:
Use map[rune]int for char counts [OK]
- Using slice instead of map for counts
- Using wrong key or value types in map
- Not initializing the map before use
package main
import "fmt"
func main() {
s := "ADOBECODEBANC"
t := "ABC"
result := minWindow(s, t)
fmt.Println(result)
}
func minWindow(s, t string) string {
need := make(map[rune]int)
for _, c := range t {
need[c]++
}
have := make(map[rune]int)
left, right := 0, 0
count := 0
minLen := len(s) + 1
start := 0
for right < len(s) {
c := rune(s[right])
if need[c] > 0 {
have[c]++
if have[c] <= need[c] {
count++
}
}
for count == len(t) {
if right-left+1 < minLen {
minLen = right - left + 1
start = left
}
leftChar := rune(s[left])
if need[leftChar] > 0 {
have[leftChar]--
if have[leftChar] < need[leftChar] {
count--
}
}
left++
}
right++
}
if minLen > len(s) {
return ""
}
return s[start : start+minLen]
}Solution
Step 1: Understand the algorithm logic
The code uses two pointers to find the smallest substring inscontaining all chars oft. It updates the minimum length and start index when a valid window is found.Step 2: Trace the example input
Fors = "ADOBECODEBANC"andt = "ABC", the minimum window substring containing 'A', 'B', and 'C' is "BANC".Final Answer:
"BANC" -> Option AQuick Check:
Minimum window substring for example = "BANC" [OK]
- Not updating minimum length correctly
- Counting characters incorrectly
- Returning empty string when valid window exists
func minWindow(s, t string) string {
need := make(map[rune]int)
for _, c := range t {
need[c]++
}
have := make(map[rune]int)
left, right := 0, 0
count := 0
minLen := len(s) + 1
start := 0
for right < len(s) {
c := rune(s[right])
if need[c] > 0 {
have[c]++
if have[c] == need[c] {
count++
}
}
for count == len(t) {
if right-left+1 < minLen {
minLen = right - left + 1
start = left
}
leftChar := rune(s[left])
if need[leftChar] > 0 {
have[leftChar]--
if have[leftChar] < need[leftChar] {
count--
}
}
left++
}
right++
}
if minLen > len(s) {
return ""
}
return s[start : start+minLen]
}Solution
Step 1: Understand the role of count and need map
The variablecounttracks how many required characters are matched. The mapneedholds unique characters fromt. Usinglen(t)counts total characters including duplicates, which is incorrect.Step 2: Identify the correct condition for a valid window
The condition should check ifcountequals the number of unique characters needed, which islen(need). Changing the condition fixes the bug.Final Answer:
Change count == len(t) to count == len(need) in the inner loop condition -> Option DQuick Check:
Use unique char count for window check [OK]
- Confusing total chars with unique chars count
- Incorrect loop boundary causing index errors
- Ignoring character presence check before counting
s = "aabbccdd" and t = "abc", what is the minimum window substring that contains all characters of t at least once? Consider the following approach:
- Use two pointers to slide over s
- Count characters needed from t
- Shrink window when all chars matched
What is the correct minimum window substring?Solution
Step 1: Identify characters needed and their counts
Characters needed are 'a', 'b', and 'c'. We want the smallest substring containing at least one of each.Step 2: Find the smallest substring in s containing 'a', 'b', and 'c'
Checking substrings: "abbc" (positions 1-4) contains 'a', 'b', 'c' and is smaller than "aabbc" or others. "abc" does not appear as continuous substring. "bcca" is not in order and does not appear as substring.Final Answer:
"abbc" -> Option AQuick Check:
Smallest substring with all chars = "abbc" [OK]
- Assuming substring must be exact order of t
- Choosing longer substrings unnecessarily
- Ignoring repeated characters in s
Ready to prove it?
Pass the test and this pattern moves unknown
