首页 > 代码库 > [LeetCode] Minimum Window Substring

[LeetCode] Minimum Window Substring

Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).

For example, S = "ADOBECODEBANC" T = "ABC"

Minimum window is "BANC".

Note: If there is no such window in S that covers all characters in T, return the emtpy string "".

If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S.

看看From LeetCode Discuss:

O(n) Solution

The method I used was to map the characters and how many are in the substring vs how many are needed.  If all the values are non-negative, then you can remove characters from the start of the substring until you reach a negative, and if there‘s a negative, you add to the end of the substring until it is 0 again.  You continue this until you‘ve reached the end of S, and then remove characters until you have a negative count for one of the characters.

Going through the example, S="ADOBECODEBANC" and T="ABC".  Starting out, the map has the values A=-1, B=-1, C=-1, and has a count of 3 negatives.  Adding the first letter increases A to 0, which removes a negative, leaving a count of 2.  You can count the others as well, since they will never become negative, resulting in A=0,B=0,C=0,D=1,O=1,E=1 when you add the C.  Since the negative count is 0, you start removing characters from the start, which is A, dropping it to -1, and switching back to adding at the end.

You then add to the end until you reach an A again, which results in A=0,B=1,C=0,D=2,E=2,O=2 and a count of 0.  Remove from the start until you reach a negative again, which removes D,O,B,E,C, since B‘s removal only drops it to 0, not a negative.  At that point, the substring is "ODEBA" and C = -1.  Add to the end until you reach a C and you have "ODEBANC", and remove from the start until you get a negative again, leaving "ANC". You‘ve reached the end of the string and have a negative, so there is no shorter string remaining with all the characters.

You can retrieve the shortest substring by taking the start and end indices of the mapped substring whenever you switch from removing to adding and storing them if they are shorter than the previous shortest.  If you never switch from removing to adding, then the result is the empty string.

If S="BANC" and T="ABC", then the result is adding until you reach "BANC", switching to remove, hitting a negative (and therefore copying those lengths at 0 and 3), and attempting to add beyond the end which ends the algorithm with the substring starting at 0 and ending at 3.

As every character gets adding once and removed once or less, it takes 2n steps at most to complete the algorithm, an O(n) solution.

class Solution {  private:      int count1[256];      int count2[256];  public:      string minWindow(string S, string T) {          // Start typing your C/C++ solution below          // DO NOT write int main() function          if (T.size() == 0 || S.size() == 0)            return "";                      memset(count1, 0, sizeof(count1));         memset(count2, 0, sizeof(count2));                 for(int i = 0; i < T.size(); i++)         {             count1[T[i]]++;             count2[T[i]]++;         }                 int count = T.size();                  int start = 0;         int minSize = INT_MAX;         int minStart;        for(int end = 0; end < S.size(); end++)         {             if (count2[S[end]] > 0)            {                 count1[S[end]]--;                 if (count1[S[end]] >= 0)                     count--;             }                          if (count == 0)             {                 while(true)                 {                     if (count2[S[start]] > 0)                     {                         if (count1[S[start]] < 0)                             count1[S[start]]++;                         else                             break;                     }                     start++;                 }                              if (minSize > end - start + 1)                {                     minSize = end - start + 1;                    minStart = start;                }            }         }                 if (minSize == INT_MAX)             return "";                string ret(S, minStart, minSize);                 return ret;             } };