438. 找到字符串中所有字母异位词
自己尝试解法
func findAnagrams(s string, p string) []int {
p_byte := []byte(p)
l_p := len(p_byte)
sort.Slice(p_byte, func(i, j int) bool {
return p_byte[i] < p_byte[j]
})
s_byte := []byte(s)
l_s := len(s_byte)
ret := make([]int, 0, l_s-l_p)
res := 0
for i := 0; i <= (l_s - l_p); i++ {
sort.Slice(s_byte[i:i+l_p], func(i, j int) bool {
return s_byte[i] < s_byte[j]
})
res = bytes.Compare(s_byte[i:i+l_p], p_byte)
if res == 0 {
ret = append(ret, i)
}
}
return ret
}
上述解法有两处行不通
1.
sort.Slice(s_byte[i:i+l_p], func(i, j int) bool {
return s_byte[i] < s_byte[j]
})
由于匿名函数的原因,这个写法不可行。在上面那段代码中,需要排序的slice是s_byte,对于slice中的第i或者第j个元素,less function直接对s_byte[i]和s_byte[j]进行比较操作;而在下面那段代码中,需要排序的slice是
s_byte[i:i+l_p]
,对于slice中的第i或者第j个元素,less function 仍然是对s_byte[i]
和s_byte[j]
进行比较操作。实际上,less function应该比较的对象是s_byte[i+I]
和s_byte[j+I]
。此处详见参考
修改代码如下:
for i := 0; i <= (l_s - l_p); i++ {
s_ := s_byte[i : i+l_p]
sort.Slice(s_, func(i, j int) bool {
return s_[i] < s_[j]
})
2.没有考虑到Slice为引用传递,每次根据ascii码排序交换后都会改变底层的数组,导致最后结果出错。还没有找到对应的解决办法,欢迎小伙伴们评论。
官解
func findAnagrams(s, p string) (ans []int) {
sLen, pLen := len(s), len(p)
if sLen < pLen {
return
}
var sCount, pCount [26]int
for i, ch := range p {
sCount[s[i]-'a']++
pCount[ch-'a']++
}
if sCount == pCount {
ans = append(ans, 0)
}
for i, ch := range s[:sLen-pLen] {
sCount[ch-'a']--
sCount[s[i+pLen]-'a']++
if sCount == pCount {
ans = append(ans, i+1)
}
}
return
}
基本思想是滑动窗口
首先判定s最前面的一组,然后依次向后移动
注意理解第二个for循环中ch和i+pLen的关系
sCount[ch-'a']--
sCount[s[i+pLen]-'a']++
这就构成了滑动窗口