携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第 15 天,点击查看活动详情
找到字符串中所有字母异位词
原题地址
给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。
示例 1:
输入: s = "cbaebabacd", p = "abc"
输出: [0,6]
解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。
示例 2:
输入: s = "abab", p = "ab"
输出: [0,1,2]
解释:
起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。
起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。
起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词。
提示:
1 <= s.length, p.length <= 3 *s和p仅包含小写字母
思路分析
方法一
- 题目中需要找出
s中p的所有异位词的下标结果集; - 首先若
s.length < p.length,那么结果肯定为false; - 遍历
s,以i < s.length - p.length + 1为终止条件,首先截取跟p长度相同的字符串,来判断是否跟p是异位词,若是,则将下标放入结果集res中;最后返回res即可; - 那么,我们需要一个辅助函数来判断两个字符串是否为异位词,方法一使用的是先拆分成数组,然后排序后再组成字符串,比较两个字符串是否相同的方式。使用的是两个异位词排序后肯定是一样的思想。但是这种方法,在执行时超出时间限制了。
方法二
- 步骤1~4 同方法一,唯一不同的就是判断两个字符串是否为异位词的方法;
- 两个字符串是异位词意味着 两个字符串中字符出现的种类和次数均相等。根据题意可知字符串只包含 26 个小写字母,所以定义一个长度为
26的数组res,先遍历记录字符串s,得到其中每个字符出现的次数,然后遍历字符串t,减去res中对应的次数,若res[i]<0,返回 false 即可。 - 使用方法二,执行测试用例时,未发生超时。
AC 代码
方法一
/**
* @param {string} s
* @param {string} p
* @return {number[]}
*/
var findAnagrams = function(s, p) {
if(s.length < p.length) return []
const res = []
const len = p.length
for(let i = 0; i < s.length - len + 1; i++) {
const str = s.substr(i, len)
if(isWords(str, p)) {
res.push(i)
}
}
return res
};
var isWords = function(s, t) {
return s.split('').sort().join('') === t.split('').sort().join('')
}
结果:
- 执行结果: 超出时间限制
方法二
/**
* @param {string} s
* @param {string} p
* @return {number[]}
*/
var findAnagrams = function(s, p) {
if(s.length < p.length) return []
const res = []
const len = p.length
for(let i = 0; i < s.length - len + 1; i++) {
const str = s.substr(i, len)
if(isWords(str, p)) {
res.push(i)
}
}
return res
};
var isWords = function(s, t) {
const res = new Array(26).fill(0)
for (let i = 0; i < s.length; ++i) {
res[s.codePointAt(i) - 'a'.codePointAt(0)]++
}
for (let i = 0; i < t.length; ++i) {
res[t.codePointAt(i) - 'a'.codePointAt(0)]--
if (res[t.codePointAt(i) - 'a'.codePointAt(0)] < 0) {
return false
}
}
return true
}
结果:
- 执行结果: 通过
- 执行用时:3872 ms, 在所有 JavaScript 提交中击败了5.35%的用户
- 内存消耗:48.2 MB, 在所有 JavaScript 提交中击败了44.12%的用户
- 通过测试用例:61 / 61