567.字符串的排列 - medium

给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的排列。

换句话说,第一个字符串的排列之一是第二个字符串的子串。

示例1:

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

示例2:

输入: s1= "ab" s2 = "eidboaoo"
输出: False

注意:

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

 

 

 

思路:

  • 滑动窗口 + 左右指针,和 "438.找到字符串中所有字母异位词"、"76.最小覆盖子串";
  • 用 count 记录滑动窗口中 s1 中字符出现的次数,当某一个字符出现的次数,超过 s1 中的次数,则不用记录;
  • 当 count == 0 时,表示窗口中的字符个数等于 s1 中的字符个数,则停下来判断是否满足子串这一个条件。

class Solution {
    public boolean checkInclusion(String s1, String s2) {
        int n1 = s1.length(), n2 = s2.length();
        if(n1 > n2) return false;
        int left = 0, right = 0, count = n1;
        int[] needs = new int[26]; // s1 的字符统计
        int[] windows = new int[26]; //滑动窗口
        for(char c : s1.toCharArray()) needs[c-'a']++; // s1 数组
        while(right < n2){
            char cr = s2.charAt(right);
            right++; // 窗口右移
            if(needs[cr-'a'] > 0){
                windows[cr-'a']++;
                if(windows[cr-'a'] <= needs[cr-'a']) count--; // count是否改变
            }
            while(count == 0){
                if(right - left == n1) return true; //满足条件,返回 true
                char cl = s2.charAt(left);
                windows[cl - 'a']--;
                if(needs[cl - 'a'] > 0){ //如果这个字符也是 s1 中的字符
                    if(windows[cl - 'a'] < needs[cl - 'a']) count++; //查看是否更新 count
                }
                left++; //缩小窗口
            }
        }
        return false;
    }
}

 

posted @ 2020-11-11 16:52  星海寻梦233  阅读(82)  评论(0编辑  收藏  举报