一起刷LeetCode——无重复字符的最长子串(滑动窗口)

67 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第10天,点击查看活动详情

无重复字符的最长子串

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

来源 leetcode.cn/problems/lo…

分析

  • 找出不含重复字符的最长子串,所以要对字符串进行遍历,最终的最长子串的长度是有条件的,因此,使用滑动窗口来管理遍历到的子串,为了确定子串的长度,有两种方法

双指针+对象

  • 使用两个指针,分别指向没有重复字符的子串的首尾,左指针和右指针均从0开始,右指针一直在左指针的右边,右指针不断向右移动,直到右指针和左指针指向的字符相同,此时记录子串长度,接着左指针向右移动,右指针继续向右移动,在找到和左指针重复的位置,依次类推,直到遍历结束,因此时间复杂度是O(n),只用了两个指针的空间

代码

/**
 * @param {string} s
 * @return {number}
 */
var lengthOfLongestSubstring = function(s) {
    let size = s.length
    let vis = {}
    let len = 0
    for(let left=0,right=0;right < s.length;right++) {
        if(!vis[s[right]]) {
            vis[s[right]]=1
        } else {
            vis[s[right]]++
        }
        while(vis[s[right]] > 1) {
            vis[s[left++]]--
        }
        len = Math.max(len, right - left +1)
    }
    return len
};

复杂数据结构(Map/Set)

  • 遍历过程中,把字符串的字符使用Map/Set维护起来,当碰到重复的字符时,获取当前数据结构中元素的个数即无重复字符的子串的长度,然后把这个数据结构中重复的字符删掉,继续遍历,遍历到的和复杂数据结构中的字符不同的字符时,添加到数据里,遍历结束,即可得到无重复字符子串的最长的长度。时间复杂度也是O(n),但是空间复杂度会比较高
  • 因为set数据具有唯一性,以Set作为例子

代码

/**
 * @param {string} s
 * @return {number}
 */
var lengthOfLongestSubstring = function(s) {
    let maxLength = 0
    let left = 0
    let charSet = new Set()
    for (let right = 0; right < s.length; right++){
        while (charSet.has(s[right])){
            charSet.delete(s[left])
            left += 1
        }
        charSet.add(s[right])
        maxLength = Math.max(maxLength, right - left + 1)
    }
    return maxLength
};

总结

  • 对字符串子串操作的题目中,指针相对来说比较轻巧灵便,在一些字符串的题目中,双指针算的上是一个推荐的解法
  • 今天也是有收获的一天