挑战LeetCode100题(TS版本)打卡第三天

115 阅读2分钟

挑战LeetCode热题100(TS版本)

打卡第三天

1.无重复字符的最长子串

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。 示例 1:

输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:

输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:

输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列, 不是子串。

思路一:暴力破解(判断是否重复)

    function lengthOfLongestSubstring(s: string): number {
    // 暴力破解-超时
    // let max = 0
    // for(let i=0;i<s.length;i++) {
    //     for(let j=i;j<s.length;j++) {
    //         const c = s.slice(i,j+1)
    //         if(isRepeat(c)) {
    //             continue
    //         } else {
    //             max = Math.max(max, c.length)
    //         }
    //     }
    // }
    // return max
};

function isRepeat(s: string): boolean {
    const set = new Set()
    for(let i=0;i<s.length;i++) {
        if(!set.has(s[i])) {
            set.add(s[i])
        } else {
            return true
        }
    }
    return false
}

思路二:滑动窗口

function lengthOfLongestSubstring(s: string): number {
    const set = new Set()
    let left = 0
    let rigth = 0
    let max = 0
    while(rigth < s.length) {
        if(!set.has(s[rigth])) {
            set.add(s[rigth])
            rigth++
        } else {
            set.delete(s[left])
            left++
        }
        max = Math.max(max, set.size)
    }

    return max
};

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

给定两个字符串 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" 的异位词。

思路:ASCII + 滑动窗口

function findAnagrams(s: string, p: string): number[] {
    // ASCII + 滚动窗口
    const result: number[] = []
    const sCount: number[] = new Array(26).fill(0)
    const pCount: number[] = new Array(26).fill(0)

    for(let i=0;i<p.length;i++) {
        pCount[p.charCodeAt(i) - 'a'.charCodeAt(0)]++
    }

    let left  = 0
    let right = 0

    while(right < s.length) {
        sCount[s.charCodeAt(right) - 'a'.charCodeAt(0)]++
        if(right - left + 1 === p.length) {
            if(sCount.every((c,i) => c === pCount[i])) {
                result.push(left)
            }

            sCount[s.charCodeAt(left) - 'a'.charCodeAt(0)]--
            left++
        }
        right++
    }
    return result
};

总结:

  • 第一道题目使用暴力破解会超时,不推荐使用;
  • 第二道题目巧妙的借用ASCII,每次达到匹配串长度时只需要比对对应的ASCII出现次数即可