打怪升级之旅第四天

57 阅读1分钟

每天进步一点点

算法开始第三天 无重复最长子串 难度 medium

无重复最长子串

题目描述

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: s = "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

暴力解法 不推荐

思路分析

/**
 * 暴力破解
 * @param {string} str 
 * @returns 
 * 时间复杂度:O(n^2)
 * 空间复杂度: O(n) 使用了数组
 */

const longerSubStr = function (str) {
  let max = 0
  let len = str.length
  for (let i = 0; i < len; i++) {
    let chars = [str.charAt(i)]
    let j = i
    let isRepetition = true
    while (isRepetition) {
      j++
      if (j >= len) break
      let currentChar = str.charAt(j)
      if (!chars.includes(currentChar)) {
        chars.push(currentChar)
      } else {
        isRepetition = false
      }
    }
    max = Math.max(chars.length, max)
  }
  return max
}

console.time('longerSubStr')
const result = longerSubStr('abcabcbb')
console.timeEnd('longerSubStr') // 0.27m
console.log('>>>><<<', result) //3

哈希 + 双指针

思路分析

定义两个指针l, r。 r 不断自增 将每个字符出现的次数放在哈希表中 如果当前的字符出现过 我们需要将l指针右移 知道当前字符出现次数为1

/**
 * 双指针 + 哈希表解法
 * 定义两个指针l, r。
 * r 不断自增 
 * 将每个字符出现的次数 如果当前的字符出现过 我们需要将l指针右移
 *  时间复杂度:O(n)
 * 空间复杂度: O(n)
 */
const longerSubStr1 = function (str) {
  let len = str.length
  let max = 0
  let map = new Map()
  for (l = 0, r = 0; r < len; r++) {
    let char = str.charAt(r)
    let frequency = map.has(char) ? 1 : map.get(char) + 1
    map.set(char, frequency)
    while (map.get(char) > 1) { // 这个while 再这个循环中最多执行n次 
      let lChar = str.charAt(l)
      let frequency = map.get(lChar) - 1
      map.set(lChar, frequency)
      i++
    }
    max = Math.max(max, r - l + 1)
  }
  return max
}

console.time('longerSubStr')
const result1 = longerSubStr1('abcdefg')
console.timeEnd('longerSubStr') // 0.141ms
console.log('>>>><<<', result1)

BayBay!!!