76. 最小覆蓋子串
給你一個字符串 s 、一個字符串 t 。返回 s 中涵蓋 t 所有字符的最小子串。如果 s 中不存在涵蓋 t 所有字符的子串,則返回空字符串 "" 。
注意:
- 對於
t中重複字符,我們尋找的子字符串中該字符數量必須不少於t中該字符數量。 - 如果
s中存在這樣的子串,我們保證它是唯一的答案。
示例 1:
輸入:s = "ADOBECODEBANC", t = "ABC"
輸出:"BANC"
解釋:最小覆蓋子串 "BANC" 包含來自字符串 t 的 'A'、'B' 和 'C'。
示例 2:
輸入:s = "a", t = "a"
輸出:"a"
解釋:整個字符串 s 是最小覆蓋子串。
示例 3:
輸入: s = "a", t = "aa"
輸出: ""
解釋: t 中兩個字符 'a' 均應包含在 s 的子串中,
因此沒有符合條件的子字符串,返回空字符串。
提示:
m == s.lengthn == t.length1 <= m, n <= 105s和t由英文字母組成
class Solution {
public String minWindow(String s, String t) {
int[]need = new int[128];
for(char c:t.toCharArray()){
need[c]++;
}
// 定義滑動窗口左右指針,收縮和擴張
int left = 0;
int right = 0;
// 當前滿足條件的字符串的長度,找最小
int minLen = Integer.MAX_VALUE;
// 結束滿足條件,t 中還需要尋找的字符串數量
int needcount = t.length();
// 最小字串起始位置,後續結合 minLen 計算最短字符串
int start=0;
// 右指針不斷向右擴張
while(right<s.length()){
char sCharAtRight = s.charAt(right);
// 如果找到還需要的字符
if(need[sCharAtRight]>0){
needcount--;
}
// 所需字符減一,可以為負數,表示多餘該字符
need[sCharAtRight]--;
// 窗口擴張
right++;
// 所有需要字符都已經找到,開始收縮左指針
while(needcount==0){
// 更新最短字符串
if(right-left<minLen){
minLen = right-left;
start = left;
}
char sCharAtLeft = s.charAt(left);
// 所需字符加一
need[sCharAtLeft]++;
// 説明少了一個所需字符串,數量加 1
if(need[sCharAtLeft]>0){
needcount++;
}
// 窗口收縮
left++;
}
}
if(minLen==Integer.MAX_VALUE){return "";}
return s.substring(start,start+minLen);
}
}