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

题目

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

一. 两层循环

外层依次遍历字符串的每个字符,内层使用set保存已出现字符,使用两个变量分别标记开始和结尾,如果内层的长度已经大于标记,则移动标记到当前位置,如果出现重复,则结束内层循环。

js实现

/**
 * @param {string} s
 * @return {number}
 */
var lengthOfLongestSubstring = function(s) {
  if (!s.length) {
    return 0
  }
  var start = 0
  var end = 1
  for (var i=0;i<s.length;i++) {
    var set = new Set()
    set.add(s[i])
    for (var j=i+1;j<s.length;j++) {
      if (set.has(s[j])) {
        break
      }
      if (j + 1 - i > end - start) {
        start = i
        end = j + 1
      }
      set.add(s[j])
    }
  }
  return end - start
};

复杂度分析

时间复杂度:O(n2)

空间复杂度:O(n)

测试结果

✔ Accepted
  ✔ 987/987 cases passed (300 ms)
  ✔ Your runtime beats 23.95 % of javascript submissions
  ✔ Your memory usage beats 24.1 % of javascript submissions (41.8 MB)

二. 优化的两层循环

在两层循环的基础上,我们可以不使用两个变量标记开始和结尾,我们只需要标记长度即可,所以,只使用一个变量表示长度即可。

js实现

/**
 * @param {string} s
 * @return {number}
 */
var lengthOfLongestSubstring = function(s) {
  if (!s.length) {
    return 0
  }
  var len = 1
  for (var i=0;i<s.length;i++) {
    var set = new Set()
    set.add(s[i])
    for (var j=i+1;j<s.length;j++) {
      if (set.has(s[j])) {
        break
      }
      set.add(s[j])
      if (set.size > len) {
        len = set.size
      }
    }
  }
  return len
};

复杂度分析

时间复杂度:O(n2)

空间复杂度:O(n)

测试结果

✔ Accepted
  ✔ 987/987 cases passed (276 ms)
  ✔ Your runtime beats 24.27 % of javascript submissions
  ✔ Your memory usage beats 22.38 % of javascript submissions (41.8 MB)

三. 滑动窗口

定义子字符串的左右边界,起始时均为0,检测右边界是否重复,如果没有重复,则右边界向右滑动,如果重复,则左边界向右滑动。

js实现

/**
 * @param {string} s
 * @return {number}
 */
var lengthOfLongestSubstring = function(s) {
  var len = s.length
  var set = new Set()
  var result=0, i=0, j=0
  while (i < len && j < len) {
    if (!set.has(s[j])) {
      set.add(s[j])
      j++
      result = Math.max(result, j - i)
    } else {
      set.delete(s[i])
      i++
    }
  }
  return result
};

复杂度分析

时间复杂度:O(2n)

空间复杂度:O(n)

测试结果

✔ Accepted
  ✔ 987/987 cases passed (104 ms)
  ✔ Your runtime beats 93.28 % of javascript submissions
  ✔ Your memory usage beats 78.94 % of javascript submissions (38.7 MB)

四. 优化的滑动窗口

在滑动窗口的基础上,我们使用Map代替Set保存值对应的位置,遍历时,如果值在Map中存在且在左边界内,则表示值对应位置及它的的左侧无需再进行判断,这样我们最多只需遍历一次即可得出结果。

js实现

/**
 * @param {string} s
 * @return {number}
 */
var lengthOfLongestSubstring = function(s) {
  var len = s.length
  var map = new Map()
  var result=0, i=0, j=0
  while (i < len && j < len) {
    if (map.has(s[j])) {
      i = Math.max(map.get(s[j]), i)
    }
    result = Math.max(result, j+1-i)
    map.set(s[j], ++j)
  }
  return result
};

复杂度分析

时间复杂度:O(n)

空间复杂度:O(n)

测试结果

✔ Accepted
  ✔ 987/987 cases passed (92 ms)
  ✔ Your runtime beats 98.97 % of javascript submissions
  ✔ Your memory usage beats 82.05 % of javascript submissions (38.1 MB)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值