Bird
Raised Fist0
DSA Rustprogramming~5 mins

Minimum Window Substring in DSA Rust - Time & Space Complexity

Choose your learning style10 modes available
Time Complexity: Minimum Window Substring
O(n + m)
Understanding Time 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 grows?

Scenario Under Consideration

Analyze the time complexity of the following code snippet.

fn min_window(s: &str, t: &str) -> String {
    use std::collections::HashMap;
    let mut need = HashMap::new();
    for c in t.chars() { *need.entry(c).or_insert(0) += 1; }
    let (mut left, mut right, mut count) = (0, 0, t.len());
    let s_chars: Vec = s.chars().collect();
    let mut min_len = usize::MAX;
    let mut start = 0;

    while right < s_chars.len() {
        if let Some(n) = need.get_mut(&s_chars[right]) {
            if *n > 0 { count -= 1; }
            *n -= 1;
        }
        right += 1;

        while count == 0 {
            if right - left < min_len {
                min_len = right - left;
                start = left;
            }
            if let Some(n) = need.get_mut(&s_chars[left]) {
                *n += 1;
                if *n > 0 { count += 1; }
            }
            left += 1;
        }
    }

    if min_len == usize::MAX { "".to_string() } else { s_chars[start..start+min_len].iter().collect() }
}

This code finds the smallest substring in s that contains all characters of t using a sliding window approach.

Identify Repeating Operations

Identify the loops, recursion, array traversals that repeat.

  • Primary operation: The while loop that moves the right pointer over the string s, and the inner while loop that moves the left pointer to shrink the window.
  • How many times: Each character in s is visited at most twice: once when right moves forward, once when left moves forward.
How Execution Grows With Input

As the input string s grows, the algorithm moves two pointers across it. Each pointer moves forward without going back, so the total steps grow roughly in proportion to the length of s.

Input Size (n)Approx. Operations
10About 20 steps (each pointer moves across 10 characters)
100About 200 steps
1000About 2000 steps

Pattern observation: The total work grows roughly linearly with input size, doubling input roughly doubles the work.

Final Time Complexity

Time Complexity: O(n + m)

This means the time grows linearly with the size of the input string s (length n) plus the size of the target string t (length m).

Common Mistake

[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, once by each pointer, so the total steps add up linearly, not multiply.

Interview Connect

Understanding this sliding window approach and its linear time complexity shows you can handle efficient substring search problems, a common skill in coding challenges and interviews.

Self-Check

"What if the target string t contains all unique characters? How would the time complexity change?"

Practice

(1/5)
1. What is the main goal of the Minimum Window Substring problem?
easy
A. Reverse the entire string
B. Sort a string in ascending order
C. Count the number of vowels in a string
D. Find the smallest substring in a string that contains all characters of another string

Solution

  1. Step 1: Understand the problem statement

    The problem asks to find the smallest part of a string that includes all characters from another string.
  2. Step 2: Identify the goal

    We want the minimum length substring that contains all required characters, not sorting or counting.
  3. Final Answer:

    Find the smallest substring in a string that contains all characters of another string -> Option D
  4. Quick Check:

    Minimum Window Substring = smallest substring containing all chars [OK]
Hint: Look for smallest substring covering all target chars [OK]
Common Mistakes:
  • Confusing with sorting or reversing strings
  • Thinking it counts characters instead of finding substring
  • Ignoring the requirement to include all characters
2. Which Rust data structure is most suitable to track character counts when solving Minimum Window Substring?
easy
A. Vec<char>
B. HashMap
C. LinkedList<char>
D. BinaryHeap<char>

Solution

  1. Step 1: Identify the need for character frequency tracking

    We need to count how many times each character appears in the target string and current window.
  2. Step 2: Choose a data structure that maps characters to counts

    A HashMap allows storing counts for each character efficiently.
  3. Final Answer:

    HashMap -> Option B
  4. Quick Check:

    Use HashMap for char counts [OK]
Hint: Use HashMap to map chars to counts [OK]
Common Mistakes:
  • Using Vec<char> which doesn't track counts
  • Choosing LinkedList which is inefficient here
  • Using BinaryHeap which is for priority, not counts
3. What is the output of the following Rust code snippet for Minimum Window Substring?
let s = "ADOBECODEBANC";
let t = "ABC";
let result = min_window(s, t);
println!("{}", result);

fn min_window(s: &str, t: &str) -> String {
    use std::collections::HashMap;
    let mut need = HashMap::new();
    for c in t.chars() {
        *need.entry(c).or_insert(0) += 1;
    }
    let (mut left, mut right, mut count) = (0, 0, 0);
    let mut min_len = usize::MAX;
    let mut start = 0;
    let mut window = HashMap::new();
    let s_chars: Vec<char> = s.chars().collect();
    while right < s_chars.len() {
        let c = s_chars[right];
        if need.contains_key(&c) {
            *window.entry(c).or_insert(0) += 1;
            if window[&c] == need[&c] {
                count += 1;
            }
        }
        while count == need.len() {
            if right - left + 1 < min_len {
                min_len = right - left + 1;
                start = left;
            }
            let left_char = s_chars[left];
            if need.contains_key(&left_char) {
                *window.entry(left_char).or_insert(0) -= 1;
                if window[&left_char] < need[&left_char] {
                    count -= 1;
                }
            }
            left += 1;
        }
        right += 1;
    }
    if min_len == usize::MAX {
        "".to_string()
    } else {
        s_chars[start..start + min_len].iter().collect()
    }
}
medium
A. "BANC"
B. "ADOBEC"
C. "CODEBA"
D. "ABC"

Solution

  1. Step 1: Understand the input strings

    We want the smallest substring of "ADOBECODEBANC" containing all chars of "ABC".
  2. Step 2: Trace the sliding window algorithm

    The code finds "BANC" as the minimum window containing 'A', 'B', and 'C'.
  3. Final Answer:

    "BANC" -> Option A
  4. Quick Check:

    Minimum window substring = "BANC" [OK]
Hint: Trace sliding window to find smallest valid substring [OK]
Common Mistakes:
  • Choosing first found substring instead of minimum
  • Ignoring character counts in window
  • Confusing substring boundaries
4. Identify the bug in this Rust code snippet for Minimum Window Substring:
fn min_window(s: &str, t: &str) -> String {
    use std::collections::HashMap;
    let mut need = HashMap::new();
    for c in t.chars() {
        *need.entry(c).or_insert(0) += 1;
    }
    let (mut left, mut right, mut count) = (0, 0, 0);
    let mut min_len = usize::MAX;
    let mut start = 0;
    let mut window = HashMap::new();
    let s_chars: Vec<char> = s.chars().collect();
    while right <= s_chars.len() {
        let c = s_chars[right];
        if need.contains_key(&c) {
            *window.entry(c).or_insert(0) += 1;
            if window[&c] == need[&c] {
                count += 1;
            }
        }
        while count == need.len() {
            if right - left + 1 < min_len {
                min_len = right - left + 1;
                start = left;
            }
            let left_char = s_chars[left];
            if need.contains_key(&left_char) {
                *window.entry(left_char).or_insert(0) -= 1;
                if window[&left_char] < need[&left_char] {
                    count -= 1;
                }
            }
            left += 1;
        }
        right += 1;
    }
    if min_len == usize::MAX {
        "".to_string()
    } else {
        s_chars[start..start + min_len].iter().collect()
    }
}
medium
A. The function returns a &str instead of String
B. The count variable is never incremented
C. The loop condition should be right < s_chars.len() instead of <= to avoid out-of-bounds
D. The window HashMap is not initialized

Solution

  1. Step 1: Check the while loop boundary

    The loop uses right <= s_chars.len(), which causes out-of-bounds access at s_chars[right].
  2. Step 2: Correct the loop condition

    Changing it to right < s_chars.len() prevents accessing beyond the vector length.
  3. Final Answer:

    The loop condition should be right < s_chars.len() instead of <= to avoid out-of-bounds -> Option C
  4. Quick Check:

    Loop boundary must prevent out-of-bounds [OK]
Hint: Check loop limits to avoid indexing errors [OK]
Common Mistakes:
  • Using <= instead of < in loop condition
  • Ignoring vector length causing panic
  • Not incrementing count correctly
5. Given the strings s = "aabbccdd" and t = "abc", what is the minimum window substring that contains all characters of t? Consider the Rust sliding window approach.
hard
A. "aabbc"
B. "abc"
C. "abbc"
D. "bcca"

Solution

  1. Step 1: Identify required characters and counts

    String t requires 'a', 'b', and 'c' once each.
  2. Step 2: Find smallest substring in s containing all

    "aabbc" (positions 0 to 4) contains 'a', 'a', 'b', 'b', 'c' and is the smallest window covering all required chars.
  3. Final Answer:

    "aabbc" -> Option A
  4. Quick Check:

    Minimum window substring = "aabbc" [OK]
Hint: Slide window to cover all chars, then shrink to minimum [OK]
Common Mistakes:
  • Choosing substring missing one required character
  • Picking longer substring than necessary
  • Ignoring character counts in window
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard