Java實現 LeetCode 76.最小覆蓋子串(滑動窗口)

給你一個字符串 S、一個字符串 T,請在字符串 S 裏面找出:包含 T 所有字符的最小子串。

示例:

輸入: S = “ADOBECODEBANC”, T = “ABC”
輸出: “BANC”
說明:

如果 S 中不存這樣的子串,則返回空字符串 “”。
如果 S 中存在這樣的子串,我們保證它是唯一的答案。

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/minimum-window-substring
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

解:
滑動窗口的最常見的模板

  • 這道題的思路是:
  • 1、用一個[left,right)表示窗口
  • 2、distance用來記錄滿足t中字符的個數。先當distance<tlen時,right++(右窗口向右移動),
  • 當distance==tlen時,說明當前的這個窗口中正好包含了t中的所有字符。
  • 3、這個時候,我們開始壓縮窗口,向後找最小覆蓋的窗口。我們將left++(左窗口向右移動),移動到distance<tlen的時候,
  • 我們又開始重複2步驟的操作。直到right移動到了slen就結束啦~
  • 那麼現在剩下的問題是處理窗口移動過程中的變化:
  • 1、用map或者數組記錄t中每個字符的出現次數,用have存儲窗口中包含的t字符串的字符出現次數
  • 2、在移動right的過程中,判斷s[right]是否是t中的字符,是則將這個字符加入到have中,如果have中這個字符出現的次數==map中這個字符的個數,那麼distance++
  • 3、在移動left的過程中,將s[left]移出窗口,直到distance < tlen
  • 4、在distance==tlen的時候,我們需要記錄此時子串的長度、開始、結尾(或者此時的結果子串),當出現更小的長度時,我們再更新。
  • 具體細節在代碼中實現。
class Solution {
    public String minWindow(String s, String t) {
        int sLen = s.length();
		int tLen = t.length();
		
		char[] ss = s.toCharArray();
		char[] tt = t.toCharArray();
		
		int minLen = sLen+1;//初始化爲一個不可達到的值
		int start = 0;//開始截取點
		int left = 0, right = 0;
		int distance = 0;//記錄滿足t中字符的個數
		
		Map<Character, Integer> map = new HashMap<Character, Integer>();
		//記錄t中各字符出現的次數
		for(int i = 0; i < tLen; i++) {
			map.put(tt[i], map.getOrDefault(tt[i], 0) + 1);
		}
		//記錄當前窗口中的字符
		Map<Character, Integer> have = new HashMap<>();
		
		//滑動窗口
		while(right < sLen) {
			char c = ss[right];
			right++;
			if(map.containsKey(c)) { 
				have.put(c, have.getOrDefault(c, 0) + 1);
				if(have.get(c).compareTo(map.get(c)) == 0) {//當匹配完成t中的一種字符時
					distance++;
					
				}
			}
			
			//當窗口中包含了t中所有的字符,我們開始壓縮,並向右繼續判斷
			while(distance == map.size()) {
				//當這個窗口長度更小時,記錄當前窗口的開始,和當前子串的長度
				if(right - left < minLen) {
					start = left;
					minLen = right - left;
				}
				//開始像右壓縮,直到distance又小於tLen
				c = ss[left];
				left++;
				if(map.containsKey(c)) {
					have.put(c, have.get(c)-1);
					if(have.get(c) < map.get(c)) {
						distance--;
					}
				}
			}
		}
		
		return minLen == sLen+1 ? "" : s.substring(start, start+minLen);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章