76.最小覆盖子串
# 76.最小覆盖子串
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
输入:s = "ADOBECODEBANC", t = "ABC" 输出:"BANC"
- 双指针法,每一轮循环先让right指针先向右移动,直至指针区间包含模式串,再让left开始向右移动直至left+1到right区间(首次)不包含模式串,此时双指针之间即为一个覆盖子串。但是这道题有一个比较麻烦的地方,模式串中的字符可以重复,因此难点在于两个地方,如何判断在right指针移动中首次包含字串和left移动中首次不包含子串。我的做法如下:
- 创建一个HashMap tmodel构建在模式串中每个字符和出现次数的映射,另一个HashMap del来存放两个指针区间的模式串字符和对应在指针区间出现次数的映射关系。再设置一个ArrayList full容器,存放当前还需要匹配找到的字符串,初始list容器把模式串的字符全部填入(可以重复)。主串每找到一个模式串含有字符就在del中记录出现次数加一,并从list中移除该元素(如果有),当full容器全部排空则说明首次匹配。
- 左指针移动时,每找到一个模式串含有的元素就在del中对应字符次数减一,当该字符在del中出现次数等于tmodel中的次数时,则表明若删去该字符,指针区间不包含子串。此时要记得在full中添加该字符(下次right右移找到该字符,即找到新的覆盖子串)。
见鬼的是,只有一个主串长度比较离谱的用例没通过,推测是容器扩容失败溢出了。
public String minWindow(String s, String t) {
Map<Character,Integer> tmodel=new HashMap<>(),del=new HashMap<>();
List<Character> full=new ArrayList<>();
int i=0,resl=0,resr=s.length();
while(i<t.length())
{
if(!tmodel.containsKey(t.charAt(i)))
tmodel.put(t.charAt(i),1);
else
tmodel.put(t.charAt(i),tmodel.get(t.charAt(i))+1);
full.add(t.charAt(i));
i++;
}
int left=0,right=0;
while(left<s.length()&&right<s.length())
{
while(right<s.length())
{
char c=s.charAt(right);
if(tmodel.containsKey(c))
{
if(full.contains(c))
full.remove(Character.valueOf(c));
if(!del.containsKey(c))
del.put(c,1);
else
del.put(c,del.get(c)+1);
}
if(full.size()==0)
break;
right++;
}
if(right==s.length())
break;
while(left<s.length())
{
char c=s.charAt(left);
if(tmodel.containsKey(c))
{
if(del.get(c)==tmodel.get(c))
{
if(right-left<resr-resl)
{
resl=left;
resr=right;
}
del.put(c,del.get(c)-1);
full.add(c);
left++;
right++;
break;
}
del.put(c,del.get(c)-1);
}
left++;
}
}
if(resr<s.length())
return s.substring(resl,resr+1);
return s.substring(0,0);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
编辑 (opens new window)
上次更新: 2023/12/15, 15:49:57