题目

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

示例 1:
**

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

示例 2:

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

示例 3:

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

方案一(双指针/滑动窗口+hashmap)

func lengthOfLongestSubstring(s string) int {
    var i, j int // i 在前
    m := map[rune]bool{}
    max_str_length := 0

    rune_s := []rune(s)
    for i < len(s) {
        if _, ok := m[rune_s[i]]; ok { // 存在
            delete(m, rune_s[j])
            if max_str_length < i - j {
                max_str_length = i - j
            }
            j += 1
        } else {
            m[rune_s[i]] = true
            i += 1
        }
    }
    if max_str_length < i - j {
        max_str_length = i - j
    }

    return max_str_length
}
  • 上述方案可以优化,一次性跳过多个字符,而非目前这样一次跳过一个字符

方案二(leetcode)

func lengthOfLongestSubstring(s string) int {
    // 思路:
    // 使用 滑动窗口 遍历一遍
    // 使用 lastOccurred 记录每个字符最近出现的 index
    // 遍历的时候先看看是否在 lastOccurred 中存在
    // 如果存在更新 start 到最近 index + 1
    // 否则 start 不变
    // 更新或者不更新 start 之后比较 当前索引和 start 之间的长度与 maxLength 比较取最大
    // 更新当前 字符 在 lastOccurred 中的 索引

    var start int = 0
    var maxLength = 0
    lastOccurred := make(map[int32]int)

    //开始遍历 s
    for i, ch := range s {
        // 首先查找是否存在 lastOccurred
        lastI, exist := lastOccurred[ch]

        // 如果存在 并且 大于等于 start index
        // 注意,等于 start 也要更新,因为 start 包含在前子字符串
        if exist && lastI >= start {
            // 更新 start
            start = lastI + 1
        }
        // 不存在则不操作
        // 然后更新 maxLength
        if i - start + 1 > maxLength {
            maxLength = i - start + 1
        }
        // 更新当前字符 ch 在 lastoccurred 中的位置
        lastOccurred[ch] = i
    } 
    return maxLength
}
  • 以上答案为 leetcode 答案

https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/wu-zhong-fu-zi-fu-de-zui-chang-zi-chuan-by-leetcod/

原文

https://leetcode-cn.com/explore/learn/card/hash-table/207/conclusion/826/