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

package a9;

import java.util.*;

class Solution {
    public static void main(String[] args) {
        String s = "aabaa";
        String p = "aa";
        System.out.println(new Solution().findAnagrams(s, p));
    }

    //暴力法
    /*public List<Integer> findAnagrams(String s, String p) {
        char[] charP = p.toCharArray();
        Arrays.sort(charP);
        String pp = String.valueOf(charP);
        HashSet<String> set = new HashSet<>();
        set.add(pp);
        List<Integer> ans = new ArrayList<>();
        for(int i = 0; i < s.length() - p.length() + 1; i++){
            String sub = s.substring(i, i + p.length());
            char[] charS = sub.toCharArray();
            Arrays.sort(charS);
            String ss = new String(charS);
            if(set.contains(ss)){
                ans.add(i);
            }
        }
        return ans;
    }*/

    //滑动数组
    /*public List<Integer> findAnagrams(String s, String p) {
        if(s.length() < p.length()) return Collections.emptyList();
        List<Integer> res = new ArrayList<>();
        int[] arr1 = new int[26];
        int[] arr2 = new int[26];
        for(int i = 0; i < p.length(); i++){
            arr1[s.charAt(i) - 'a']++;
            arr2[p.charAt(i) - 'a']++;
        }
        if(Arrays.equals(arr1, arr2)) res.add(0);

        for(int begin = 0, end = p.length(); end < s.length(); end++, begin++) {
            arr1[s.charAt(begin) - 'a']--;
            arr1[s.charAt(end) - 'a']++;
            if(Arrays.equals(arr1, arr2)) res.add(begin + 1);
         }
        return res;
    }*/

    //优化滑动数组(未优化的情况下,判断是否相等需要O(p.length),优化后只需要O(1))
    public List<Integer> findAnagrams(String s, String p) {
        int sLen = s.length(), pLen = p.length();
        if(sLen < pLen) return Collections.emptyList();
        List<Integer> res = new ArrayList<>();
        int[] arr1 = new int[26];
        int[] arr2 = new int[26];
        for(int i = 0; i < pLen; i++) {
            arr1[s.charAt(i) - 'a']++;
            arr2[p.charAt(i) - 'a']++;
        }
        int differ = 0;//两个串不同的字母的个数
        for(int i = 0; i < 26; i++) {
            if(arr1[i] != arr2[i]) {
                differ++;
            }
        }
        if(differ == 0) res.add(0);
        for(int begin = 0, end = pLen; end < sLen; end++, begin++) {
            int beginChar = s.charAt(begin) - 'a', endChar = s.charAt(end) - 'a';
            arr1[beginChar]--;
            if(arr1[beginChar] == arr2[beginChar]) {
                differ--;
            } else if(arr1[beginChar] == arr2[beginChar] - 1){//同一个字母只记录一次
                differ++;
            }
            arr1[endChar]++;
            if(arr1[endChar] == arr2[endChar]) {
                differ--;
            } else if (arr1[endChar] == arr2[endChar] + 1) {//同一个字母只记录一次
                differ++;
            }
            if(differ == 0) res.add(begin + 1);
        }
        return res;
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值