给定两个字符串 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; } }