LeetCode 438 找到字符串中所有字母异位词

本文探讨了使用滑动窗口技巧解决字符串中的字谜替换问题。通过两种方法对比,介绍了如何减少时间复杂度,避免重复计算,并展示了具体的Go语言实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 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
}

滑动窗口的思想不要忘!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值