字符串中的变位词——滑动窗口

52 阅读1分钟

image.png

代码1

滑动窗口

  1. 用长度为26的数组来记录各个单词的数量,然后直接比较数组即可
  2. 滑动窗口,新加的字母,删除队尾的字母
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 中每次移动我们只改变了两个字母,但我们每次比较都是比较整个数组

  1. 其中 diff 记录有几种字符不同,也就是 diff 的取值范围为(0 ~ 26)
  2. 判断条件也就是,新加的字符 x 如果在之前数量为 0 则,则在加之后,diff 的值加 1
  3. 如果在加之后的 x 的数量为 0, 则在加之后 diff 减一
  4. 同理 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
}