S长度为M,T长度为N

  • 暴力枚举所有子串肯定超时,枚举S所有子串复杂的O(M^2),再每个和T校验,O(M^2*N)
  • 假设答案法:
    • 答案就是一段子串,这段子串假设从a点出发,那么如果我把每个点可能性都给枚举了,说明肯定能抓到正确答案
    • 具体实现采用滑动窗口,定住一个start点,然后另一个指针end往右不断的找,维护一个窗口wind,当第一次满足了要求的时候抓一次答案,因为此时一定是以start开头最短的子串情况
    • 抓到start开头最短的之后,start++,滑动窗口左边右移,开始尝试下一个点,直到所有的点都枚举完成
      public String minWindow (String S, String T) {
        if(S==null||T==null||S.length()<T.length()) return "";
        //遍历,假设答案法:每次可能的子串都抓,每次抓1.起点2.长度
        //两个指针start,end;存一个窗口中已有字符
        int start = 0,end = 0;
        char[] tChars = T.toCharArray();
        char[] sChars = S.toCharArray();
        int sN = sChars.length;
        int tN = tChars.length;
        //存一个窗口中已有字符
        HashMap<Character,Integer> wind = new HashMap<>();
        //存T中各个字符个数
        HashMap<Character,Integer> tCharMap = new HashMap<>();
        for(int i = 0;i<tN;i++){
            tCharMap.put(tChars[i],tCharMap.getOrDefault(tChars[i],0)+1);
        }
        //窗口[)
        int minLen = Integer.MAX_VALUE;
        int minStart = 0;
        while(start<sN&&end<=sN){
            int len = end-start;
            boolean isNoFull = noCapAll(wind, tCharMap);
            if(end!=sN&&isNoFull){
                //右边动,进一个
                wind.put(sChars[end],wind.getOrDefault(sChars[end],0)+1);
                end++;
                continue;
            }else if(len<minLen&&!isNoFull){
                //装够了,抓一个答案
                minStart = start;
                minLen = len;
            }
            //左边边界右移
            wind.put(sChars[start],wind.get(sChars[start])-1);
            start++;
        }
        return minLen==Integer.MAX_VALUE?"":new String(sChars,minStart,minLen);
      }
      public boolean noCapAll(HashMap<Character,Integer> wind,HashMap<Character,Integer> tCharMap){
        //遍历tCharMap,看看wind是否满足tCharMap中的所有元素要求的个数
        for(Map.Entry<Character,Integer> entry:tCharMap.entrySet()){
            Character key = entry.getKey();
            int value = entry.getValue();
            if(!wind.containsKey(key)||wind.get(key)<value){
                return true;
            }
        }
        return false;
      }