Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Minimum Window Substring 🧠

LeetCode Link: Minimum Window Substring

Difficulty: Hard

Problem Explanation 📝

Problem: LeetCode 76 - Minimum Window Substring

Description: Given two strings s and t, return the minimum window in s that contains all the characters of t. If there is no such window in s that covers all characters in t, return an empty string.

Intuition: To find the minimum window substring, we can use the sliding window technique. The idea is to maintain two pointers, left and right, to create a window in s. By expanding and contracting the window, we can find the minimum window substring that contains all the characters of t.

Approach:

  1. We start by initializing two pointers, left and right, to the first index of s.
  2. We initialize two frequency maps, targetFreq and windowFreq, to store the frequencies of characters in t and the current window of s, respectively.
  3. We initialize variables, count and minLen, to keep track of the count of characters in t that are present in the current window and the minimum window length found so far.
  4. We iterate through s using the right pointer:
  • Increment the frequency of the character at s[right] in windowFreq.
  • If the frequency of the character at s[right] in windowFreq is less than or equal to the frequency of the same character in targetFreq, increment the count.
  • If count is equal to the length of t, it means we have found a valid window that contains all the characters of t.
  • Update minLen if the current window length is smaller.
  • Move the left pointer to contract the window:
  • Decrement the frequency of the character at s[left] in windowFreq.
  • If the frequency of the character at s[left] in windowFreq becomes less than the frequency in targetFreq, decrement the count.
  • Move the left pointer to the right to search for the next valid window.
  1. Repeat steps 4 and 5 until the right pointer reaches the end of s.
  2. Return the minimum window substring found based on minLen. If no valid window is found, return an empty string.

⌛ Time Complexity: The time complexity is O(n), where n is the length of s. We iterate through s once using the sliding window approach.

💾 Space Complexity: The space complexity is O(1) as both targetFreq and windowFreq have a fixed size of 128 to represent ASCII characters.

Solutions 💡

Cpp 💻

class Solution {
  public:
    string minWindow(string s, string t) {
        vector<int> targetFreq(128, 0);
        vector<int> windowFreq(128, 0);

        for (char ch : t) {
            targetFreq[ch]++;
        }

        int left = 0;
        int right = 0;
        int count = 0;
        int minLen = INT_MAX;
        int minStart = 0;

        while (right < s.length()) {
            windowFreq[s[right]]++;

            if (windowFreq[s[right]] <= targetFreq[s[right]]) {
                count++;
            }

            while (count == t.length()) {
                if (right - left + 1 < minLen) {
                    minLen = right - left + 1;
                    minStart = left;
                }

                windowFreq[s[left]]--;

                if (windowFreq[s[left]] < targetFreq[s[left]]) {
                    count--;
                }

                left++;
            }

            right++;
        }

        return (minLen == INT_MAX) ? "" : s.substr(minStart, minLen);
    }
};

// class Solution {
// public:
//     string minWindow(string s, string t) {
//         if(t.length() > s.length())
//             return "";

//         unordered_map<char, int> M;
//         for(int i = 0; i < t.size(); i++)
//             M[t[i]]++;

//         int L = 0, R = 0;
//         int count = t.size();  // No. of chars in t that need to be n S
//         int minLength = INT_MAX;
//         int minStart = 0; // We have to return string, so this variable is for storing teh starting index

//         while(R < s.size()) {
//             if(M[s[R]] > 0)     // If we find an element from T(which we put in M)
//                 count--;

//             // We will decrease the value here also, since count only counts unique elements
//             // Elements in M will decrease till 0(which then decreases count)
//             // and elements that dont exist in M will be -ve
//             M[s[R]]--;
//             R++;
//             while(count == 0) {
//                 if(R-L < minLength) {
//                     minLength = R-L;
//                     minStart = L;
//                 }
//                 M[s[L]]++; // Updating the value in Map
//                 // If the current L element is from T, then increase count
//                 if(M[s[L]] > 0) {
//                     count++;
//                 }
//                 L++;
//             }
//         }
//         // If the ans is empty string, minLength(= MAX_INT) will not be changed
//         if (minLength != INT_MAX) {
//             return s.substr(minStart, minLength);
//         }
//         return "";
//     }
// };

/*
class Solution {
public:
    string minWindow(string s, string t) {
        int cnt[128] = {}, diff = t.size();
        for(int i = 0; i < t.size(); i++)
            cnt[t[i]]++;
        int left = 0, right = 0, idx = 0, size = 2e5;
        while(right < s.size()) {
            if(cnt[s[right++]]-- > 0)
                diff--;
            while(diff == 0) {
                if(right-left < size)
                    size = right-(idx = left);
                if(cnt[s[left++]]++ == 0)
                    diff++;
            }
        }
        return (size == 2e5) ? "" : s.substr(idx, size);
    }
};
*/

Python 🐍

class Solution:
    def minWindow(self, s: str, t: str) -> str:
        if not s or not t:
            return ""

        char_freq_t = {}
        for char in t:
            char_freq_t[char] = char_freq_t.get(char, 0) + 1

        left, right = 0, 0
        char_freq_temp = {}
        required_chars = len(char_freq_t)
        formed_chars = 0
        min_length = float("inf")
        min_window = ""

        while right < len(s):
            char_freq_temp[s[right]] = char_freq_temp.get(s[right], 0) + 1

            if (
                s[right] in char_freq_t
                and char_freq_temp[s[right]] == char_freq_t[s[right]]
            ):
                formed_chars += 1

            while left <= right and formed_chars == required_chars:
                if right - left + 1 < min_length:
                    min_length = right - left + 1
                    min_window = s[left : right + 1]

                char_freq_temp[s[left]] -= 1
                if (
                    s[left] in char_freq_t
                    and char_freq_temp[s[left]] < char_freq_t[s[left]]
                ):
                    formed_chars -= 1

                left += 1

            right += 1

        return min_window