美文网首页
438. 找到字符串中所有字母异位词

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

作者: 土豆泥加冰谢谢 | 来源:发表于2020-11-27 19:57 被阅读0次

    给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引。

    字符串只包含小写英文字母,并且字符串 s 和 p 的长度都不超过 20100。

    说明:

    字母异位词指字母相同,但排列不同的字符串。
    不考虑答案输出的顺序。
    示例 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" 的字母异位词。

            public List<Integer> findAnagrams(String s, String p) {
                List<Integer> ret=new ArrayList<>();
                //排除边界条件
                if (p.length()>s.length()){
                    return ret;
                }
                //子串问题,属于滑动窗口问题
                //首先定义窗口性质[left,right],窗口内为p的字母异位词,因此窗口有大小限制,与p长度相等
                //先将p转为HashMap存储便于对比
                Map<Character,Integer> pMap=new HashMap<>();
                for(int i=0;i<p.length();i++){
                    char item=p.charAt(i);
                    addData(item,pMap);
                }
                Map<Character,Integer> windowData=new HashMap<>();
                int left=0;
                int right=0;
                while (right<s.length()){
                    char item=s.charAt(right);
                    if (right-left<p.length()){
                        //当窗口还不满足数量条件时,我们直接放入数据,并右移right
                        addData(item,windowData);
                        right++;
                        continue;
                    }
                    System.out.println("此时的right:"+right);
                    if (isAnagram(windowData,pMap)){
                        //满足异位词
                        //记录下left
                        ret.add(left);
                    }
                    //因为窗口数量已满足了,所以为了下一轮循环继续满足,无论是否满足异位词,均需要移除left,left进位,添加当前位,right进位
                    //移除最左一位
                    removeData(s.charAt(left),windowData);
                    left++;
                    addData(item,windowData);
                    right++;
                }
                //不要漏掉最后结尾的情况,因为走完循环,此时right已经超出,所以最后一个窗口并未参与判断
                if(right-left==p.length()){
                    if (isAnagram(windowData,pMap)){
                        ret.add(left);
                    }
                }
                return ret;
    
            }
            //存入每个字符以及对应数量,因为异位词一定是所有字符都是数量相等的
            private void addData(Character key,Map<Character,Integer> map){
                if (map.containsKey(key)){
                    map.put(key,map.get(key)+1);
                }else {
                    map.put(key,1);
                }
            }
    
            private void removeData(Character key,Map<Character,Integer> map){
                if (map.get(key)>1){
                    map.put(key,map.get(key)-1);
                }else {
                    map.remove(key);
                }
            }
    
            //辅助函数,判断窗口中字符是否为p的异位词
            private boolean isAnagram(Map<Character,Integer> windowData,Map<Character,Integer> p){
                boolean ret=true;
                for (Character key:windowData.keySet()){
                    //注意Integer用equals比较值
                    if (!windowData.get(key).equals(p.get(key))){
                        return false;
                    }
                }
                return ret;
            }
    

    相关文章

      网友评论

          本文标题:438. 找到字符串中所有字母异位词

          本文链接:https://www.haomeiwen.com/subject/qlkfwktx.html