76. Minimum Window Substring

来源:互联网 发布:网络整合营销的道与术 编辑:程序博客网 时间:2024/06/03 20:46

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 empty string "".

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


题意:给定字符串s和t,求s包含t中所有字符的最小子串;s的子串不仅需要包含所有t中的字符,且字符数目同样要大于等于t中对于字符的数目。

这个题的思路在于“窗口”的移动 ,“窗口”指的是符合要求的s的子串,但不一定是最小的。

那么我们要做的就是先找到第一个符合要求的窗口,记录下窗口的长度,

例如S = "ADOBECODEBANC"
T = "ABC".

我们先找到第一个窗口"ADOBEC",记录下它的长度为6和起始下标0;

第二步删除窗口的第一个字符'A',然后找到第二个出现'A'的地方,这样我们就得到了第二个窗口"BECODEBA",记录下窗口的长度8,起始下标为3;

继续上述步骤,得到下一个窗口,"CODEBA",记录窗口长度6,起始下标5;

……

最后一个窗口"BANC",长度为4,起始坐标为9,

这样每个找到一个窗口就更新窗口长度和起始坐标,最后得到最小的窗口。

在解题过程中我们需要借助字典或者HashMap来记录字符出现的次数。

下面是方法具体实现的代码:

class Solution {    public String minWindow(String s, String t) {        if(s.isEmpty() || t.isEmpty())            return "";        int[] tt = new int[128];                           //字典,以字符值作为下标,元素值为字符出现的次数        boolean[] b = new boolean[128];                    //用来区分字符是否是字符串t中的        for(int i=0;i<t.length();i++){                    //赋值            tt[t.charAt(i)]++;            b[t.charAt(i)] = true;        }                            int left = 0;                            //窗口左端        int count = 0;                           //记录当前窗口中有多少个字符串t中的字符        int minLen = s.length()+1;                //记录窗口最小长度        int minLeft = 0;                          //最小窗口起始下标        for(int i=0;i<s.length();i++){            if(b[s.charAt(i)]){                tt[s.charAt(i)]--;                                 if(tt[s.charAt(i)]>=0)            //当小于0时,表示当前窗口的某个字符数目已经超过了t中该字符的数目,count值不变                    count++;            }            while(count == t.length()){         //窗口锁定,记录窗口长度和起始下标                if(i-left+1 < minLen){                    minLen = i-left+1;                    minLeft = left;                }                if(b[s.charAt(left)]){                    tt[s.charAt(left)]++;                    if(tt[s.charAt(left)] > 0)                        count--;                }                left++;            }        }        return minLen==s.length()+1 ? "" : s.substring(minLeft,minLeft+minLen);    }}
这个方法中的2个数组可以用1个HashMap代替。另外解决这道题的这种窗口模型可以适用于很多种类似的情况。