LeetCode无重复字符的最长子串JS实现

无重复字符的最长子串

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

示例:

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

请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。

解法

暴力法

由于时间限制,会出现 TLE

思路

逐个检查所有的子字符串,看它是否不含有重复的字符。

复杂度

时间复杂度: O ( n 3 ) O(n^3) O(n3)

滑动窗口

思路

滑动窗口是数组/字符串问题中常用的抽象概念。 窗口通常是在数组/字符串中由开始和结束索引定义的一系列元素的集合,即 [i, j)[i,j)(左闭,右开)。而滑动窗口是可以将两个边界向某一方向“滑动”的窗口。例如,我们将 [i, j)[i,j) 向右滑动 11 个元素,则它将变为 [ i + 1 , j + 1 ) [i+1, j+1) [i+1,j+1)(左闭,右开)

我们使用 哈希表(Map) 将字符存储在当前窗口 [ i , j ) [i, j) [i,j)(最初 j = ij=i)中。 然后我们向右侧滑动索引 j j j,如果它不在 哈希表(Map) 中,我们会继续滑动 j j j。直到 s [ j ] s[j] s[j] 已经存在于 哈希表(Map) 中。此时,我们找到的没有重复字符的最长子字符串将会以索引 i i i 开头。如果我们对所有的 i i i 这样做,就可以得到答案。

/**
 * @param {string} s
 * @return {number}
 */
var lengthOfLongestSubstring = function (s) {
    var n = s.length
    var map = new Map()
    var ans = 0, i = 0, j = 0;
    while (i < n && j < n) {
        if (!map.has(s[j])){
            map.set(s[j],j++)
            ans = Math.max(ans, j - i);
        }
        else {
            map.delete(s[i],i++)
        }
    }
    return ans;
};
复杂度
  • 时间复杂度: O ( 2 n ) = O ( n ) O(2n) = O(n) O(2n)=O(n),在最糟糕的情况下,每个字符将被 i i i j j j 访问两次。
  • 空间复杂度: O ( min ⁡ ( m , n ) ) O(\min(m,n)) O(min(m,n)),与之前的方法相同。滑动窗口法需要 O ( k ) O(k) O(k)的空间,其中 k k k 表示 Set 的大小。而 Set 的大小取决于字符串 n n n的大小以及字符集 / 字母 m m m的大小。

优化的滑动窗口

上述的方法最多需要执行 2n 个步骤。事实上,它可以被进一步优化为仅需要 n 个步骤。我们可以定义字符到索引的映射,而不是使用集合来判断一个字符是否存在。 当我们找到重复的字符时,我们可以立即跳过该窗口。

/**
 * @param {string} s
 * @return {number}
 */
var lengthOfLongestSubstring = function (s) {
    var n = s.length
    var map = new Map()
    var ans = 0, i = 0, j = 0;
    for (let j = 0, i = 0; j < n; j++) {
        if (map.has(s[j])) {
            i = Math.max(map.get(s[j]), i);
        }
        ans = Math.max(ans, j - i + 1);
        map.set(s[j],j+1)
    }
    return ans;
};
复杂度
  • 时间复杂度: O ( n ) O(n) O(n)

  • 时间复杂度: O ( n 3 ) O(n^3) O(n3)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值