1、首先想到的就是暴力解决,记录字符串p中各个字符的出现次数。然后对s的每个字符进行遍历,计算以s[i]为起点,长为len(p)的子串中的各个字符数,对比与p是否相同,相同则将i加入到返回列表,否则break遍历s中的下一个字符。
注意:坑在了map跟slice更新上,传指针即使复制了值,原有的值还是会被改变。同时这种暴力算法,在leetcode提交中出现了超出时间限制的错误。
func findAnagrams(s string, p string) []int {
var numMap map[rune]int=make(map[rune]int)
var tmpS, tmpP []rune=[]rune(s), []rune(p)
var res []int
for _, v:=range []rune(p){ numMap[v]++ }
for i:=0; i<len(tmpS)-len(tmpP)+1; i++{
tmpMap:=make(map[rune]int)
for k, v:=range numMap{ tmpMap[k]=v }
flag:=true
for j:=0; j<len(tmpP); j++{
// fmt.Println(i, j, tmpMap, res)
if _, ok:=tmpMap[tmpS[i+j]]; ok{ //字典中存在该值
tmpMap[tmpS[i+j]]--
if tmpMap[tmpS[i+j]]<0 {
// fmt.Println("-----------------")
flag=false
break
}
}else{
flag=false
break
}
}
if flag==true{ res=append(res, i) }
}
return res
}
2、想办法降低时间复杂度,首先想到的就是不能对s中的每一个字符都重头遍历p长度的子串,因此维护两个列表ms以及mp,其中ms存储s中前p个字符的统计情况,mp存储p中的每个字符统计情况。比较ms与mp是否相同,之后对s中后面的字符采用如下操作,ms[s[i]]++,ms[s[i-len(p)]]--,比较修改后的ms与mp是否相同,相同,将 i 加入返回值列表。
在提交过程中出现如下错误bug:
1)编写代码错误,在ms中存储了p中字符的统计情况,导致无论如何都会将0添加到返回结果中报错。
2)忽略了初始时判断若s的长度小于p(题目给定数据长度至少为1),那么可以直接返回空结果。
func findAnagrams(s string, p string) []int {
var res []int
var lenS, lenP int=len(s), len(p)
var newS, newP []rune=[]rune(s), []rune(p)
var ms, mp []int=make([]int, 128), make([]int, 128)
if lenS==0 || lenS<lenP{ return res }
for k, v:=range newP{
ms[int(newS[k])]++
mp[int(v)]++
}
// fmt.Println(ms, mp)
if ok:=reflect.DeepEqual(ms, mp); ok {
// fmt.Println("-----------------")
res=append(res, 0)
}
for i:=lenP; i<lenS; i++{
ms[int(newS[i])]++
ms[int(newS[i-lenP])]--
if ok:=reflect.DeepEqual(ms, mp); ok { res=append(res, i-lenP+1) }
}
return res
}
滑动窗口的思想不要忘!!!!