Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情。
一、题目描述
给你两个字符串 s1 和 s2 ,写一个函数来判断 s2 是否包含 s1 的排列。如果是,返回 true ;否则,返回 false 。
换句话说,s1 的排列之一是 s2 的 子串 。
示例 1:
输入:s1 = "ab" s2 = "eidbaooo"
输出:true
解释:s2 包含 s1 的排列之一 ("ba").
示例 2:
输入:s1= "ab" s2 = "eidboaoo"
输出:false
提示:
1 <= s1.length, s2.length <= 104
s1 和 s2 仅包含小写字母
二、思路分析
题意说的是需要我们判断S2中是否包含S1字符串的排列,排列组合是我们初中就学过的一个概念,就是可以将一个字符串的字符顺序打乱,重新组成一个新的字符串,可以组成的新字符串都是该字符串的一种排列组合情况。 所以要判断是否是一个字符串的排列组合,我们只需要判断两个字符串的字符组成成份是否一致即可。 这里我们可以使用滑动窗口的思想来进行解题,解题思路如下
- 1、统计字符串s1的字符出现频率
- 2、以字符串s1的长度为窗口长度,统计每个窗口的字符频率
- 3、移动窗口,将移出窗口的字符频率减去,加上新进窗口的字符频率 很多区间问题都可以使用移动窗口这种思路来进行解题,具体AC代码如下:
三、AC代码
/**
* @param {string} s1
* @param {string} s2
* @return {boolean}
*/
var checkInclusion = function(s1, s2) {
if(s1.length > s2.length) return false;
const nums1 = new Array(26).fill(0);
const nums2 = new Array(26).fill(0);
let check = function(arr1,arr2){
for(let i = 0; i < arr1.length; i++){
if(arr1[i] != arr2[i]) return false;
}
return true;
}
for(let i = 0; i < s2.length; i++){
if(i < s1.length){
nums1[s1[i].charCodeAt()-97]++;
nums2[s2[i].charCodeAt()-97]++;
continue;
}
if(check(nums1,nums2)) return true;
nums2[s2[i - s1.length].charCodeAt()-97]--;
nums2[s2[i].charCodeAt()-97]++;
}
return check(nums1,nums2);
};