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

力扣打卡:438. 找到字符串中所有字母异位词

解题思路

思路挺多的,最重要的还是映射到数组上,进行统计

因为给定的字符就是26的小写字母,那么直接生成一个26长度的数组,数组元素是对应字符串p的字符个数

  • s 进行遍历
  • 遍历一个元素,那么将对应的arr的元素 --arr[c-'a'] 进行递减,然后判断是否小于0
  • 如果小于0
    • 判断此时的字符串p是否包含这个字符
      • 如果不包含,那么在这个字符 c 之前的就不再有可能生成异位词了
        • 检查字符的数组元素是否全部为0,如果全部为0,那么是一个异位词,如果不是,那么不是异位词
        • 索引从字符c的下一个字符开始
      • 如果包含
        • 检查此时的元素是否还有大于0的,如果没有,那么也是一个答案
        • 索引重新定位到此时c字符的倒数算第n个的c字符,这个字符也是c,只统计c这个字符的个数,统计的个数是n,也就是字符串p中的c个数
  • 如果不小于0,那么索引一直递增

代码

class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        HashSet<Character> set = new HashSet<>();
        List<Integer> ans = new ArrayList<>(); 
        int[] arr = new int[26];
        int[] copy = new int[26];

        for(char c : p.toCharArray()) {arr[c-'a']++; set.add(c);};
        System.arraycopy(arr,0,copy,0,26); // 将数组保存下来

        int idx = 0;
        int len = s.length();
        while(idx < len){
            char c = s.charAt(idx);
            if(--arr[c-'a'] < 0){
                if(set.contains(c)){ 
                    boolean hasOther = false;
                    for(int x: arr) if(x>0){hasOther = true; break;}
                    if(!hasOther){ans.add(idx-p.length());}
                    idx = back(s, c, idx-1,copy[c-'a']); // 从idx开始向左边匹配
                }else{ // 如果p中不包含这个字符,那么检查arr中是否还有元素大于0
                    boolean hasOther = false;
                    for(int x: arr) if(x>0){hasOther = true; break;}
                    if(hasOther){ // 如果含有非0的元素
                        idx++;
                    }else{ // 如果元素都是0,那么是一个异位字符
                        ans.add(idx-p.length());
                    }
                }
                System.arraycopy(copy,0,arr,0,26); // 将数组重新置位,新一轮的开始
                continue;
            }
            idx++;
        }
        boolean hasOther = false;
        for(int x : arr) if(x>0) return ans;
        ans.add(s.length()-p.length());
        return ans;
    }

    public int back(String s, char c, int p, int count){
        int cnt = 0;
        while( p>=0 ){
            if(s.charAt(p)==c) cnt++;
            if(cnt==count) break;
            p--;
        }
        return ++p; // 因为此时的字符c的个数已经小于0,所以从这个字符的下一个字符开始匹配
    }


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值