題目
最小子串覆蓋
給定一個字符串source和一個目標字符串target,在字符串source中找到包括所有目標字符串字母的子串。
樣例
給出source = "ADOBECODEBANC",target = "ABC" 滿足要求的解 "BANC"
注意
如果在source中沒有這樣的子串,返回"",如果有多個這樣的子串,返回起始位置最小的子串。
挑戰
要求時間復雜度為O(n)
說明
Java Code
在答案的子串中的字母在目標字符串中是否需要具有相同的順序?
——不需要。
解題
參考:
定義兩個字典:tgt 、map
tgt統計target中每個字符出現的次數
map統計target和source出現的公共字符個數
再檢測當tgt中所以的字符和map中的字符個數都匹配的時候就是一個子串了,再找出最小的子串就好了,程序中left值用來定義子串的右邊界,要好好理解
public class Solution { /** * @param source: A string * @param target: A string * @return: A string denote the minimum window * Return "" if there is no such a string */ public String minWindow(String source, String target) { // write your code int len1 = source.length(); int len2 = target.length(); if(len1 < len2) return ""; String result = ""; // 統計target 中各個字符串出現的次數 HashMap<Character,Integer> tgt = new HashMap<Character,Integer>(); for(int i=0;i<len2;i++){ char c = target.charAt(i); if(tgt.containsKey(c)){ tgt.put(c,tgt.get(c)+1); }else{ tgt.put(c,1); } } // 存放公共字符 HashMap<Character,Integer> map = new HashMap<Character,Integer>(); int left = 0; int minLen = len1+1; int count =0; for(int i=0;i<len1;i++){ char c = source.charAt(i); if(tgt.containsKey(c)){ if(map.containsKey(c)){ if(map.get(c)<tgt.get(c)){ count++; } map.put(c,map.get(c)+1); }else{ map.put(c,1); count++; } } // 說明是一個子串 去除left無效字符 if(count == len2){ char sc = source.charAt(left); while(!map.containsKey(sc) || map.get(sc) > tgt.get(sc)){ if(map.containsKey(sc) && map.get(sc) > tgt.get(sc)) map.put(sc,map.get(sc) - 1); left++; sc = source.charAt(left); } // 找到最小子串 if( i - left + 1 < minLen){ result = source.substring(left,i + 1); minLen = i - left + 1; } } } return result; } }
