438. 找到字符串中所有字母异位词
给定两个字符串 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 * 104
s
和 p
仅包含小写字母我的思考:
abab
**
ij
cbaebabacd
* *
i和j是一直都是相同的长度,长度为p的字符串长度
map.contains()
let i = 0 ;
代码:
let len = p.length;
let j = len - 1;
let map = new Map;
// 将q遍历放入map当中
for(let q = 0 ; q < len ; q++){
map.set(p[q] , q);
}
let arr = [];
while(j < s.length){
let flag = 0;
for(let k = i ; k <= j ; k++){
if(!map.has(s[k])){
flag = 1;
}
i++;
j++;
}
if(flag === 1){
break;
}else if(flag === 0){
arr.push(i);
}
}
时间超限:分析问题大概如下
题解:
看了一下其他大神的解法,感觉很妙
s = "abab", p = "ab"
a b a b
*
先创建一个滑窗
a b a b
* *
秒:不是一个一个进行比较,而是计算每个字母的个数,最后进行判断
滑窗思想:固定的长度,左边出去一个数,右边新进来一个数
a b a b
* *
sCnt[s.charCodeAt(j - pLen) - 'a'.charCodeAt(0)]--;
sCnt[s.charCodeAt(j) - 'a'.charCodeAt(0)]++;
代码:
function findAnagrams(s: string, p: string): number[] {
// 不用一个一个比较,比较单词出现的次数相同就可以了
let sLen = s.length;
let pLen = p.length;
if(sLen < pLen) return [];
//注意创建数组的方法
let sCnt = new Array(26).fill(0);
let pCnt = new Array(26).fill(0);
let arr = [];
// 进行创建弹窗
for(let i = 0 ; i < pLen ; i++){
sCnt[s.charCodeAt(i) - 'a'.charCodeAt(0)]++;
pCnt[p.charCodeAt(i) - 'a'.charCodeAt(0)]++;
}
// if(pCnt === sCnt){
// arr.push(0)
// } 不应该直接比较
// 比较初始窗口
if (sCnt.every((value, index) => value === pCnt[index])) {
arr.push(0);
}
// 滑窗思想
for(let j = pLen ; j < sLen ; j++){
sCnt[s.charCodeAt(j - pLen) - 'a'.charCodeAt(0)]--;
sCnt[s.charCodeAt(j) - 'a'.charCodeAt(0)]++;
if (sCnt.every((value, index) => value === pCnt[index])) {
arr.push(j-pLen + 1)
}
}
return arr;
};
// abab
错误:创建数组的时候用的是[26].fill(0)
[26].fill(0)
这种写法是有问题的,因为它不会创建一个长度为26的数组,而是创建一个包含单个元素26的数组,然后尝试对这个数组中的元素进行填充。这是由于方括号内的是数组的元素,而不是数组的长度。
错误:charCodeAt写的是charAt
通过减去 ‘a’ 的字符码,我们可以将任意小写字母转换为其在计数数组中的对应索引。例如,‘b’ 的字符码减去 ‘a’ 的字符码等于 1,所以 ‘b’ 对应于数组的索引 1。
错误:比较数组
if(pCnt === sCnt){
arr.push(0)
} 不应该直接比较
if (sCnt.every((value, index) => value === pCnt[index])) {
arr.push(0);
}
错误:初始化sCnt
错误地更新了 sCnt
数组,滑窗实在s上实现的,而不是p,最开始我直接更新了Cont。
不应该直接比较
// 比较初始窗口
if (sCnt.every((value, index) => value === pCnt[index])) {
arr.push(0);
}
// 滑窗思想
for(let j = pLen ; j < sLen ; j++){
sCnt[s.charCodeAt(j - pLen) - ‘a’.charCodeAt(0)]–;
sCnt[s.charCodeAt(j) - ‘a’.charCodeAt(0)]++;
if (sCnt.every((value, index) => value === pCnt[index])) {
arr.push(j-pLen + 1)
}
}
return arr;
};
// abab
错误:创建数组的时候用的是[26].fill(0)
`[26].fill(0)`这种写法是有问题的,因为它不会创建一个长度为26的数组,而是创建一个包含单个元素26的数组,然后尝试对这个数组中的元素进行填充。这是由于方括号内的是数组的元素,而不是数组的长度。
错误:charCodeAt写的是charAt
通过减去 ‘a’ 的字符码,我们可以将任意小写字母转换为其在计数数组中的对应索引。例如,‘b’ 的字符码减去 ‘a’ 的字符码等于 1,所以 ‘b’ 对应于数组的索引 1。
错误:比较数组
if(pCnt === sCnt){
arr.push(0)
} 不应该直接比较
if (sCnt.every((value, index) => value === pCnt[index])) {
arr.push(0);
}
错误:初始化sCnt
错误地更新了 `sCnt` 数组,滑窗实在s上实现的,而不是p,最开始我直接更新了Cont。
总结:滑窗思想还是没有深入我的骨髓啊哈哈哈,及字母的个数的方式很新颖