LeetCode——字符串的排列/找到字符串中所有字母异位词

Q:给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的排列。
换句话说,第一个字符串的排列之一是第二个字符串的子串。

示例1:
输入: s1 = "ab" s2 = "eidbaooo"
输出: True
解释: s2 包含 s1 的排列之一 ("ba").
示例2:
输入: s1= "ab" s2 = "eidboaoo"
输出: False

注意:
输入的字符串只包含小写字母
两个字符串的长度都在 [1, 10,000] 之间

A:
滑动窗口(不过我把代码的s1和s2写反了,原理没错)

public boolean checkInclusion(String s1, String s2) {
        if (s1.length() == 0)
            return s2.length() == 0;
        if (s2.length() == 0)
            return true;
        if (s1.length() < s2.length())
            return false;
        Map<Character, Integer> window = new HashMap<>();
        Map<Character, Integer> needs = new HashMap<>();
        for (int i = 0; i < s2.length(); i++) {
            if (needs.containsKey(s2.charAt(i))) {
                needs.put(s2.charAt(i), needs.get(s2.charAt(i)) + 1);
            } else {
                needs.put(s2.charAt(i), 1);
            }
        }
        int count = needs.size();//符合的大小数目
        int left = 0, right = 0;
        while (right < s1.length()) {
            //先处理右指针
            char curr = s1.charAt(right);
            if (needs.containsKey(curr)) {
                if (window.containsKey(curr)) {
                    window.put(curr, window.get(curr) + 1);
                } else {
                    window.put(curr, 1);
                }
                if (window.get(curr).equals(needs.get(curr))) {
                    count--;
                }
            }
            right++;
            //再处理左指针
            while (right - left > s2.length()) {
                char l = s1.charAt(left);
                if (window.containsKey(l)) {
                    //左指针在处理前是满足相等的,要把这个数组加回去
                    if (window.get(l).equals(needs.get(l))) {
                        count++;
                    }
                    window.put(l, window.get(l) - 1);
                }
                left++;
            }
            //左右指针处理完了,此时count=0,返回true
            if (count == 0)
                return true;
        }
        return false;
    }

Q:给定一个字符串 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" 的字母异位词。

A:

    public List<Integer> findAnagrams(String s, String p) {
        List<Integer> array = new ArrayList<>();
        if (s.length() == 0 || p.length() == 0 || s.length() < p.length())
            return array;
        int left = 0, right = 0;
        Map<Character, Integer> need = new HashMap<>();
        Map<Character, Integer> window = new HashMap<>();
        for (int i = 0; i < p.length(); i++) {
            if (need.containsKey(p.charAt(i))) {
                need.put(p.charAt(i), need.get(p.charAt(i)) + 1);
            } else {
                need.put(p.charAt(i), 1);
            }
        }
        int count = need.size();
        while(right < s.length()){
            char r = s.charAt(right);
            if(need.containsKey(r)){
                if(window.containsKey(r)){
                    window.put(r,window.get(r)+1);
                }else{
                    window.put(r,1);
                }
                if(window.get(r).equals(need.get(r))){
                    count--;
                }
            }
            right++;
            while(right-left>p.length()){
                char l = s.charAt(left);
                if(window.containsKey(l)){
                    if(window.get(l).equals(need.get(l))){
                        count++;
                    }
                    window.put(l, window.get(l) - 1);
                }
                left++;
            }
            if(count == 0){
                array.add(left);
            }
        }
        return array;
    }
posted @ 2020-04-22 11:18  Shaw_喆宇  阅读(195)  评论(0编辑  收藏  举报