【算法】求最小覆盖子串

给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字符的最小子串。
示例:
输入: S = "ADOBECODEBANC", T = "ABC"
输出: "BANC"
说明:
如果 S 中不存这样的子串,则返回空字符串 ""。
如果 S 中存在这样的子串,我们保证它是唯一的答案。
来源:力扣(LeetCode)
链接: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 }

 

posted @ 2020-05-07 13:51  盖世阿萌  阅读(426)  评论(0)    收藏  举报