代码1
滑动窗口
- 用长度为26的数组来记录各个单词的数量,然后直接比较数组即可
- 滑动窗口,新加的字母,删除队尾的字母
func checkInclusion(s1, s2 string) bool {
n, m := len(s1), len(s2)
if n > m {
return false
}
var cnt1, cnt2 [26]int
for i, ch := range s1 {
cnt1[ch-'a']++
cnt2[s2[i]-'a']++
}
if cnt1 == cnt2 {
return true
}
for i := n; i < m; i++ {
cnt2[s2[i]-'a']++
cnt2[s2[i-n]-'a']--
if cnt1 == cnt2 {
return true
}
}
return false
}
代码2:
滑动窗口优化
因为代码 1 中每次移动我们只改变了两个字母,但我们每次比较都是比较整个数组
- 其中 diff 记录有
几种字符不同,也就是 diff 的取值范围为(0 ~ 26) - 判断条件也就是,新加的字符 x 如果在之前数量为 0 则,则在加之后,diff 的值加 1
- 如果在加之后的 x 的数量为 0, 则在加之后 diff 减一
- 同理 y 的变化影响也是如此
func checkInclusion(s1, s2 string) bool {
n, m := len(s1), len(s2)
if n > m {
return false
}
cnt := [26]int{}
for i, ch := range s1 {
cnt[ch-'a']--
cnt[s2[i]-'a']++
}
diff := 0
for _, c := range cnt[:] {
if c != 0 {
diff++
}
}
if diff == 0 {
return true
}
for i := n; i < m; i++ {
x, y := s2[i]-'a', s2[i-n]-'a'
if x == y {
continue
}
if cnt[x] == 0 {
diff++
}
cnt[x]++
if cnt[x] == 0 {
diff--
}
if cnt[y] == 0 {
diff++
}
cnt[y]--
if cnt[y] == 0 {
diff--
}
if diff == 0 {
return true
}
}
return false
}
代码3:
双指针
如果左右指针形成的长度为 n 的字串,cnt[x] 依旧没有出现大于 n 的情况,那自然说明在这 n 个字符中刚好全部符合要求,
func checkInclusion(s1, s2 string) bool {
n, m := len(s1), len(s2)
if n > m {
return false
}
cnt := [26]int{}
for _, ch := range s1 {
cnt[ch-'a']--
}
left := 0
for right, ch := range s2 {
x := ch - 'a'
cnt[x]++
for cnt[x] > 0 {
cnt[s2[left]-'a']--
left++
}
if right-left+1 == n {
return true
}
}
return false
}