剑指offer 48 - 无重复字符的最长子串 - python

86 阅读2分钟

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

示例 1:

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

示例 2:

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

示例 3:

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

由于我们需要找到给定字符串的最长无重复字符子串的长度,而且需要遍历字符串中全部可能的字符,因此可以使用滑动窗口来解。

  • 设置left = 0right = 0为窗口的左右指针,窗口内不能含有重复字符

  • 右移right,每移动一位判断right指向的字符是否在窗口内已存在:

    • 如果已存在,则首先保存当前窗口的字符串,然后右移left,直到窗口内不包含right指向的字符
    • 如果不存在,则继续右移right,直到走到最后一位
  • 如果走到了最后一位,且right指向的字符在窗口内不存在,首先保存子串,再退出循环

  • 最后返回最长子串的长度

示意图如下所示:


在这里插入图片描述

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
    	# 特殊情况
        if not s: return 0
        if len(s) == 1: return 1

        r = []
        left, right = 0, 0
        while right < len(s) - 1:
            right += 1
            # 如果right指针还没有走到最后,且当前right指向的字符在窗口内不存在,继续往后
            if s[right] not in s[left:right] and right < len(s) - 1:
                continue
            # 如果right已经走到了最后,且当前right指向的字符在窗口内不存在,则保存窗口内字符串,退出循环
           elif s[right] not in s[left:right] and right == len(s) - 1:
                if len(s[left:right + 1]) > l:
                    l = len(s[left:right + 1])
                break
            else:
            	# 如果right指向的字符在窗口内已经存在,则先保存窗口字符串
            	# 再右移left指针,知道窗口字符串不再包含right指向的字符
                if len(s[left:right]) > l:
                    l = len(s[left:right])
                while s[right] in s[left:right]:
                    left += 1
                    
        return l