字符串的排列

158 阅读1分钟

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字符串的排列,排列组合是我们初中就学过的一个概念,就是可以将一个字符串的字符顺序打乱,重新组成一个新的字符串,可以组成的新字符串都是该字符串的一种排列组合情况。 所以要判断是否是一个字符串的排列组合,我们只需要判断两个字符串的字符组成成份是否一致即可。 这里我们可以使用滑动窗口的思想来进行解题,解题思路如下

image.png

  • 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);
};