【算法】求最小覆盖子串
给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字符的最小子串。
示例:
输入: S = "ADOBECODEBANC", T = "ABC"
输出: "BANC"
说明:
输出: "BANC"
说明:
如果 S 中不存这样的子串,则返回空字符串 ""。
如果 S 中存在这样的子串,我们保证它是唯一的答案。
如果 S 中存在这样的子串,我们保证它是唯一的答案。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-window-substring
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
链接:https://leetcode-cn.com/problems/minimum-window-substring
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
这个题是hard程度的,是道典型的滑动窗口题,如果这道能整明白其它的滑动窗口也不会无从下手。
滑动窗口,顾名思义窗口的大小是可变的,分别定义一个左指针和右指针,每次左右指针向右移动,这样就使窗口内的值处于变换的状态。
什么时候移动右指针呢?当窗口内的数值都不满足要求时;
什么时候移动左指针呢?当窗口内的数值满足了要求时;
本题要求最小覆盖子串,即窗口内的字母包含了给出的T字符串内的所有字母,假如T=“ABC”,S可能为“BAC”正好包含,也可能为“BAAC”包含了多个重复的,也可能还有其它的字母如“ASBVC”,因此为了更好地判定,需要两个哈希表和一个计数器。
哈希表need,用以记录T字符串内的所有字母和其出现次数,如need={'A':1,'B':1,'C':1}
哈希表have,用于记录窗口内在T字符串内的字母和出现次数,没在T内的不计,如have={'A':2,'B':0,'C':2}
计数器count,记录窗口内现在满足了几个字母的要求,当count=need的长度,则达成了一个满足条件的子串,记录其长度。
1 class Solution { 2 public String minWindow(String s, String t) { 3 HashMap<Character,Integer> have=new HashMap<>();//窗口内在t串中的字母出现次数 4 HashMap<Character,Integer> need=new HashMap<>();//t串的字母出现次数 5 int left=0,right=0,count=0; 6 int start=0,min=Integer.MAX_VALUE; 7 int len=s.length(); 8 //初始化need 9 for(char c:t.toCharArray()){ 10 need.put(c,need.getOrDefault(c,0)+1); 11 } 12 13 while(right<len){ 14 char c=s.charAt(right); 15 //如果右指针的字母在t串内则计入have 16 if(need.containsKey(c)){ 17 have.put(c,have.getOrDefault(c,0)+1); 18 //如果have中该字母和need中该字母个数相同,则count+1,即达成了一个字母的要求 19 if(have.get(c).compareTo(need.get(c))==0){ 20 count++; 21 } 22 } 23 right++; 24 //如果窗口内是符合条件的子串,则右移左指针 25 while(count==need.size()){ 26 //更新最小字串的长度和起始位置 27 if(right-left<min){ 28 start=left; 29 min=right-left; 30 } 31 char cc=s.charAt(left); 32 //如果need中有左指针的字母,在have中将其-1,若need中没有则在have中也不会记录 33 if(need.containsKey(cc)){ 34 have.put(cc,have.getOrDefault(cc,1)-1); 35 //如果该字母的个数不再满足要求,count-1 36 if(have.get(cc)<need.get(cc)){ 37 count--; 38 } 39 } 40 left++; 41 } 42 } 43 return min==Integer.MAX_VALUE?"":s.substring(start,start+min); 44 } 45 }
笨鸟就算不能先飞,最后也是可以飞的吧

浙公网安备 33010602011771号