567 字符串的排列

本文最后更新于:2022年4月9日 中午


给定两个字符串 s1s2,写一个函数来判断 s2 是否包含 s1 的排列。

换句话说,第一个字符串的排列之一是第二个字符串的子串。

示例1:

1
2
3
输入: s1 = "ab" s2 = "eidbaooo"
输出: True
解释: s2 包含 s1 的排列之一 ("ba").

示例2:

1
2
输入: s1= "ab" s2 = "eidboaoo"
输出: False

注意:

  1. 输入的字符串只包含小写字母
  2. 两个字符串的长度都在 [1, 10,000] 之间

Solution

  • 滑动窗口算法

固定窗口大小

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
# @lc code=start
class Solution:
def checkInclusion(self, s1: str, s2: str) -> bool:
needs = collections.defaultdict(int)
for char in s1:
needs[char] += 1
n1, n2 = len(s1), len(s2)
if n1>n2:
return False

for i in range(0, n2-n1+1):
match = 0
window = collections.defaultdict(int)
for c1 in s2[i:i+n1]:
if c1 in needs:
window[c1] += 1
if window[c1] == needs[c1]:
match += 1
else:
break
if match== len(needs):
return True
i += 1
return False
# @lc code=end

套用框架标准写法,提交结果性能要更好些 ?

窗口大小动态调整

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
class Solution:
def checkInclusion(self, s1: str, s2: str) -> bool:
needs = collections.defaultdict(int)
window = collections.defaultdict(int)
for char in s1:
needs[char] += 1
n1, n2 = len(s1), len(s2)
if n1>n2:
return False

match = 0
left, right = 0, 0
while right < n2:
c1 = s2[right]
if c1 in needs:
window[c1] += 1
if window[c1]==needs[c1]:
match += 1
right += 1

while match==len(needs):
if right-left==len(s1):
return True
c2 = s2[left]
if c2 in needs:
window[c2] -= 1
if window[c2] < needs[c2]:
match -= 1
left += 1

return False