Leecode 字符串中所有字母异位词

思路:使用滑动窗口 ,设置一个大小为p.length大小的窗口,窗口中的字符出现的次数用一个int类型的数组记录,数组的下标代表字符ASCII码,一个字符每出现一次就让int[字符对应的ascii] +1,当滑动窗口向右移动时,只需要更新左边移出去和右边移进来的两个字符。

代码如下:

    public static List<Integer> findAnagrams(String s, String p) {
        List<Integer> result = new ArrayList<>();
        int pLength = p.length();
        //对p字符串中所有出现的字符数进行计数,这里使用字符的ASCII码作为int数组的下标
        //如果a(ASCII为97)出现一次则 int[92]就+1;
        int[] ascii = new int[123];
        char[] chars = p.toCharArray();
        for (int i = 0;i<chars.length;i++) {
            int index = chars[i];
            ascii[index]+=1;
        }
        int[] resource = new int[123];
        for (int i =0;i<=s.length()-pLength;i++){
            int k =97;
            if (i==0){//对首个字符串中的字符数量标记
                for (int j =i;j<i+pLength;j++){
                    int index = s.charAt(j);
                    resource[index]+=1;
                }
            }else { //这里是窗口右移一个位置,删除最左侧有个字符移出去,最右侧有个字符移动进来,更新这两个字符的出现次数
                int a =s.charAt(i-1),b=s.charAt(i+pLength-1);
                resource[a]-=1;
                resource [b]+=1;
            }
            //判断两个字符串中的每个字符的数量是否相等
            while(k<123){
                if (ascii[k]==resource[k]) {
                    k++;
                    continue;
                }
                else break;
            }
            if (k==123) result.add(i);
        }
        return result;
    }

更优雅的写法:

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

        if (sLen < pLen) {
            return new ArrayList<Integer>();
        }

        List<Integer> ans = new ArrayList<Integer>();
        int[] sCount = new int[26];
        int[] pCount = new int[26];
        for (int i = 0; i < pLen; ++i) {
            ++sCount[s.charAt(i) - 'a'];
            ++pCount[p.charAt(i) - 'a'];
        }

        if (Arrays.equals(sCount, pCount)) {
            ans.add(0);
        }

        for (int i = 0; i < sLen - pLen; ++i) {
            --sCount[s.charAt(i) - 'a'];
            ++sCount[s.charAt(i + pLen) - 'a'];

            if (Arrays.equals(sCount, pCount)) {
                ans.add(i + 1);
            }
        }

        return ans;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值