力扣算法ing(9/100)

2.26 438.找到字符串中所有字母的异位词

438. 找到字符串中所有字母异位词

给定两个字符串 sp,找到 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
  • sp 仅包含小写字母

我的思考:

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

    }

时间超限:分析问题大概如下

  1. 不必要的Map使用:您使用了一个Map来存储字符串p的字符,但是您只是将字符作为键,索引作为值,这实际上并没有帮助您检查异位词。
  2. 重复检查:在每次循环中,您都从头开始检查子字符串是否为异位词,这是不必要的重复工作。
  3. 滑动窗口未实现:您的代码没有正确实现滑动窗口技术,导致每次都要重新检查整个子字符串。
  4. flag的使用:您使用flag来标记是否找到非异位词的字符,但是一旦找到,您就跳出整个循环,这会导致错过后续可能的异位词。

题解:

看了一下其他大神的解法,感觉很妙

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。

总结:滑窗思想还是没有深入我的骨髓啊哈哈哈,及字母的个数的方式很新颖

你可能感兴趣的:(小白学习算法,算法,leetcode,数据库,typescript)