76. 最小覆盖子串 (Hard)
Python统计字符串出现的次数,存为dict
count = {}
for character in message:
count.setdefault(character, 0) # 确保了键存在于 count 字典中(默认值是 0)
count[character] = count[character] + 1
class Solution(object):
def minWindow(self, s, t):
window, need = {}, {}
for i in range(len(t)):
if t[i] in need.keys():
need[t[i]] += 1
else:
window[t[i]] = 0
need[t[i]] = 1
left, right = 0,0
start = 0
valid = 0
lens = float("inf")
while right<len(s):
if s[right] in need.keys():
window[s[right]] += 1
if window[s[right]]==need[s[right]]:
valid += 1
right += 1
while valid==len(need):
if right-left<lens:
lens = right-left
start = left
if s[left] in window.keys():
if(window[s[left]]==need[s[left]]):
valid -= 1
window[s[left]] -= 1
left += 1
if lens>0 and start+lens<=len(s):
return s[start:start+lens]
else:
return ''
Java:
注意,可能存在最后一个测试案例过不了
对Integer来说,默认缓存了-128~127对应的对象,因此每次获取都一样,直接 == 即可判断;但是如果超过这个范围,就需要使用equals了,因为不在缓存范围就需要new了;同样JVM调优的时候,有时候可能会设置到修改这个 上限的点去优化,这个就貌似比较高深了,因该记住个默认值没问题了。
public String minWindow(String s, String t) {
if (t.length() > s.length()) {
return "";
}
Map<Character, Integer> need = new HashMap<>();// 统计所需字符及其数量
for (int i = 0; i < t.length(); i++) {
need.put(t.charAt(i), need.getOrDefault(t.charAt(i), 0) + 1);
}
Map<Character, Integer> window = new HashMap<>();// 统计窗口内的字符及其数量
int valid = 0;// 满足条件的字符数
int l = 0, r = 0;// left-right pointers
int min_LEN = Integer.MAX_VALUE, min_LEFT = 0;//记录最小窗口的长度和开始位置
while (r < s.length()) {
// 扩大右边界
char ch = s.charAt(r);
r++;
window.put(ch, window.getOrDefault(ch, 0) + 1);
if (window.get(ch).equals(need.get(ch))) {
valid++;
}
// 满足条件时缩小窗口
while (valid == need.size()) {
// 记录当前窗口
if (r - l < min_LEN) {
min_LEN = r - l;
min_LEFT = l;
}
// 缩小左边界
char c = s.charAt(l);
if (window.get(c).equals(need.get(c))) {
valid--;
}
window.put(c, window.get(c) - 1);
l++;
}
}
return min_LEN == Integer.MAX_VALUE ? "" : s.substring(min_LEFT, min_LEFT + min_LEN);
}
567. 字符串的排列
- 自己思路:
右指针一直向右移动,
1.如果右端点的值在s1中
1.1 如果加入window后,字符次数超过需要的了→收缩窗口(左端点右移,window次数减少)
--------重点是考察val怎么变,例子:hello
, ooolleoooleh
a) 左端点如果不是新加入的右端点,则就看之前是不是满足了needle,满足减1
b) 左端点如果是新加入的右端点,则看加入之后是不是满足了needle值+1,满足减1
2.如果右端点的值不在s1中,那么之前的全部作废,窗口从right重新开始
class Solution(object):
def checkInclusion(self, s1, s2):
need,window = {},{}
for i in range(len(s1)):
need.setdefault(s1[i],0)
window.setdefault(s1[i],0)
need[s1[i]] += 1
left, right = 0,0
val = 0
while right<len(s2):
c = s2[right]
right += 1
#如果在,就把window更新,然后判断是否和need需要的一致
#如果多加了,就得收缩区间。注意减的时候,判断要去除的左端点是否被统计过val
#如果去除的左端点刚好是我们新加入的,所以就看还未去除的window中左端点个数是否比之前多1,如果不是新加的,那就看之前是否已经统计过了
if c in need.keys():
window[c] += 1
while window[c]>need[c]:
if c==s2[left] and window[s2[left]]-1==need[s2[left]]:
val -= 1
if c!=s2[left] and window[s2[left]]==need[s2[left]]:
val -= 1
window[s2[left]]-=1
left += 1
if window[c]==need[c]:
val += 1
if val == len(need):
return True
#如果不在,left就从right开始。注意!要把之前window的清零
else:
for key in window.keys():
window[key] = 0
left = right
val = 0
return False
- 正确题解
还是以hello
, ooolleoooleh
为例。如果窗口大于t序列,比如说遍历到了oooll,那么这时候val不一样,如果一样那肯定是找到了这个区间。
438. 找到字符串中所有字母异位词
和上一道题,一模一样,就是在valid等于need的时候,把答案加入
Python版本:
class Solution(object):
def findAnagrams(self, s, p):
need, window = {},{}
left, right, val =0, 0, 0
res = []
for i in range(len(p)):
need.setdefault(p[i],0)
window.setdefault(p[i],0)
need[p[i]] += 1
while right<len(s):
c = s[right]
right += 1
if c in need.keys():
window[c] += 1
if window[c]==need[c]:
val += 1
while right-left>=len(p):
if val == len(need):
res.append(left)
d = s[left]
if d in need.keys():
if window[d]==need[d]:
val -= 1
window[d] -= 1
left += 1
return res
3. 无重复字符的最长子串
- 方法一:用队列做,先放进去无重复的,如果再放入的有重复,那么剔除第一个,直到无重复
class Solution(object):
def lengthOfLongestSubstring(self, s):
curs = []
mx = 0
for i in range(len(s)):
while curs and s[i] in curs:
curs.pop(0)
curs.append(s[i])
mx = max(mx,len(curs))
return mx
- 方法二:滑动窗口
class Solution(object):
def lengthOfLongestSubstring(self, s):
count = 0
left, right = 0, 0
window = {}
while right< len(s):
c = s[right]
window.setdefault(c,0)
window[c] += 1
right += 1
while window[c]>1:
d = s[left]
window[d]-=1
left += 1
count = max(count,right-left)
return count