【算法】Leetcode438. 找到字符串中所有字母异位词(每日一题)

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

难度中等702收藏分享切换为英文接收动态反馈

给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。

示例 1:

输入: s = "cbaebabacd", p = "abc"
输出: [0,6]
解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。

 示例 2:

输入: s = "abab", p = "ab"
输出: [0,1,2]
解释:
起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。
起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。
起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词

解题思路:

根据题目要求,我们需要在字符串 s 寻找字符串 p 的异位词。因为字符串 p 的异位词的长度一定与字符串 p 的长度相同,所以我们可以在字符串 s中构造一个长度为与字符串 p 的长度相同的滑动窗口,并在滑动中维护窗口中每种字母的数量;当窗口中每种字母的数量与字符串 p 中每种字母的数量相同时,则说明当前窗口为字符串 p 的异位词。

 

             

             

 

 

这是我第一次的解法:将字符串p的字母转为数字,与字符串s中的字串进行比较

public class LC0438 {
    public static List<Integer> findAnagrams(String s, String p) {
        List<Integer> list=new ArrayList<>();
        if(p.length()>s.length())return list;
        int count=0;
        for(int i=0;i<p.length();i++){
            count+=p.charAt(i)-96;
        }
        for(int i=0;i<s.length();i++){
            //当字符串s的剩余长度小于字符串p返回list
            if(s.length()-i<p.length())return list;
                int num=0;
                for(int j=i;j<i+p.length();j++){
                    num+=s.charAt(j)-96;
                    //当num大于count时直接break
                    if(num>count)break;
                }
                //当num等于count则是异位词
                if(num==count){
                    list.add(i);
                }
        }
        return list;
    }

    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        String s=sc.nextLine();
        String p=sc.nextLine();
        System.out.println(findAnagrams(s,p));
    }
}

但是用例是af,be时通过不了,我又加了一些判断,但是当字符串非常长的时候也会出现问题

这是我第二次的解法:用数组中对应的各字母出现次数进行比较

  public List<Integer> findAnagrams(String s, String p) {
    int sLen=s.length();int pLen=p.length();
    List<Integer> list=new ArrayList<>();
    if(sLen<pLen)return list;

    int[] pCount=new int[26];
    int dff=0;
    for(char c:p.toCharArray()){
        pCount[c-'a']+=1;
    }
    for(int i=0;i<s.length();i++){
            if(s.length()-i<p.length())return list;
        if(!p.contains(s.substring(i,i+1)))continue;
            int[] sCount=new int[26];
            for(int j=i;j<i+p.length();j++){
                if(++sCount[s.charAt(j)-'a']>pCount[s.charAt(j)-'a']){
                    break;
                }
            }
            if(Arrays.equals(pCount,sCount))list.add(i);
    }
    return list;
    }

我总共提交了三次,每次都加上了一些提前结束的判断,其中一些细节:

1.当s字符串剩余长度不足时返回list

2.当前增加的数组中值超过数组P中对应的值结束当前循环

平常写算法要多想不同方法,拓宽自己思路。竞赛或面试时才不容易思想掉线

同时多扣细节,竞赛时复杂度过高过不了的地方稍加优化可能就通过了,同时细节也是面试题算法的加分点

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值