LeetCode 算法入门 — 字符串的排列

230 阅读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. 先将 s2 分成 s1 长度连续的子串;
  2. 定义 help 方法来判断,s2 的字串中是否 含有 s1 的排列;
  3. 如果 s2 的字串中有一个含有 s1 的排列,那么返回 true,否则返回 false
  4. 最后的结果是 超出时间限制,里面有太多的循环,太多的查找了。

方法二

  1. 其他步骤还是按照方法一的来处理,优化了 help 方法;
  2. 创建长度 26 的数组 count1count2,统计 s1 字符 以及 s2 的子串出现的次数;
  3. 判断 count1.join('') === count2.join('')

AC 代码

方法一

/**
 * @param {string} s1
 * @param {string} s2
 * @return {boolean}
 */
var checkInclusion = function(s1, s2) {
    const len = s1.length
    const res = []
    for(let i = 0; i <= s2.length - len; i++) {
        res.push(help(s1, s2.substr(i, len)))
    }
    console.log(res)
    return res.some(item=>item)
};

var help = function(s1, s2) {
    for(let i = 0; i < s1.length; i++) {
        const index = s2.indexOf(s1[i])
        if(index === -1) {
            return false
        } else {
            s2 = s2.replace(s1[i], 'X')
        }
    }
    return true
}

结果: 超出时间限制

方法二

/**
 * @param {string} s1
 * @param {string} s2
 * @return {boolean}
 */
var checkInclusion = function(s1, s2) {
    const len = s1.length
    const res = []
    for(let i = 0; i <= s2.length - len; i++) {
        res.push(help(s1, s2.substr(i, len)))
    }
    console.log(res)
    return res.some(item=>item)
};

var help = function(s1, s2) {
    const count1 = new Array(26).fill(0);
    const count2 = new Array(26).fill(0);
    for(let i = 0; i < s1.length; i++) {
        count1[s1[i].charCodeAt(0) - 97]++;
        count2[s2[i].charCodeAt(0) - 97]++;
    }
    return count1.join('') === count2.join('')
}

结果:

  • 执行结果: 通过
  • 执行用时:616 ms, 在所有 JavaScript 提交中击败了16.14%的用户
  • 内存消耗:49.3 MB, 在所有 JavaScript 提交中击败了5.91%的用户
  • 通过测试用例:107 / 107

END