给你两个字符串 s1 和 s2 ,写一个函数来判断 s2 是否包含 s1 的排列。如果是,返回 true ;否则,返回 false 。
换句话说,s1 的排列之一是 s2 的 子串 。
示例 1:
输入:s1 = "ab" s2 = "eidbaooo"
输出:true
解释:s2 包含 s1 的排列之一 ("ba").
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/permutation-in-string
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解一、s2是否包含s1的排列,即s2中字串的长度和对应元素个数与s1中相同,长度卡一卡,若s1大于s2,则返回false,不大于建立两个数组分别存储元素的个数,进行比较Arrays.equals(arr1,arr2),之后若不等,对s2进行窗口滑动,进入的元素索引为s1的长度开始,退出的元素索引为(当前元素索引 - s1长度)(从最前端开始遍历走了s1长度个,下一个为当前元素,当前元素-s1的长度,即可退到首位,依次遍历,保证窗口长度不变。)进行比较
class Solution{
public boolean checkInclusion(String s1, String s2){
int m = s1.length(), n = s2.length();
if(m > n){
return false;
}
int[] cnt1 = new int[26];
int[] cnt2 = new int[26];
for(int i = 0; i < m; i++){
cnt1[s1.charAt(i) - 'a']++;
cnt2[s2.charAt(i) - 'a']++;
}
if(Arrays.equals(cnt1,cnt2)){
return true;
}
for(int i = m; i < n; i++){
cnt2[s2.charAt(i) - 'a']++;
cnt2[s2.charAt(i - m) - 'a']--;
if(Arrays.equals(cnt1,cnt2)){
return true;
}
}
return false;
}
}
题解二、用一个数组,记录同长度两个字符串的字符出现情况,统计数组内不为0的元素个数,若为0,说明s1是s2的一个字串的排列。滑动窗口,仅比较进入和退出元素对不同元素个数的影响,若进入元素前,该元素对应字符出现的抵消情况导致数组对应元素为0,则此时遍历加入的元素会导致不同元素个数上升。进入后若抵消导致数组对应元素为0,则不同元素个数下降。退出元素同理。
class Solution{
public boolean checkInclusion(String s1, String s2){
int m = s1.length();
int n = s2.length();
if(m > n){
return false;
}
int[] cnt = new int[26];
for(int i = 0; i < m; i++){
cnt[s1.charAt(i) - 'a']--;
cnt[s2.charAt(i) - 'a']++;
}
int diff = 0;
for(int i : cnt){
if(i != 0){
diff++;
}
}
if(diff == 0){
return true;
}
for(int i = m; i < n; i++){
int x = s2.charAt(i) - 'a', y = s2.charAt(i - m) - 'a';
if(x == y){
continue;
}
if(cnt[x] == 0){
diff++;
}
cnt[x]++;
if(cnt[x] == 0){
diff--;
}
if(cnt[y] == 0){
diff++;
}
cnt[y]--;
if(cnt[y] == 0){
diff--;
}
if(diff == 0){
return true;
}
}
return false;
}
}