剑指 Offer 48. 最长不含重复字符的子字符串

272 阅读1分钟

题目描述

请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。

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

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

示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

解题思路1: 双指针法+暴力循环 O(n^2)

求最长子串的长度, 子串一定是连续的, 所以我们使用2个指针来进行遍历.

  1. 如果尾指针元素不在2个指针所组成的子串, 那么尾指针往后移动, 并且更新最大长度
  2. 如果尾指针在子串中, 那么我们将头指针往移动到重复元素位置的后边, 保证2个指针所组成的子串没有重复元素, 然后继续遍历尾指针

示例代码1:

def lengthOfLongestSubstring(self, s: str) -> int:
        if not s:
            return 0
        left, right = 0, 0
        result = 1
        while right < len(s) - 1:
            right += 1
            if s[right] not in s[left:right]:
                result = max(right - left + 1, result)
            else:
                while s[right] in s[left:right]:
                    left += 1
        return result

解题思路2: 双指针法+Map O(n)

同样的双指针思想, 我们使用map可以将时间复杂度优化到O(n)

  1. 判断当前遍历的字符是否在map中, 如果不在map中, 我们就将当前字符加入到map, 以 字符为key, index+1 为value
  2. 如果在map中, 我们就将头指针设置为之前记录在map中,当前元素的index

示例代码2:

def lengthOfLongestSubstring(self, s: str) -> int:
    if not s:
        return 0
    left = 0
    result = 0
    dic = {}
    for i in range(0, len(s)):
        right = s[i]
        if right in dic:
            left = max(dic[right], left)
        dic[right] = i + 1
        result = max(result, i - left + 1)
    return result