跳转至

滑动窗口

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

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

class Solution:
    @staticmethod
    def lengthOfLongestSubstring(s: str) -> int:
        # 执行超过时间限制
        s_len = len(s)
        max_len = 0
        for i in range(s_len):
            for j in range(i + 1, s_len + 1):  # 切片,左开右闭
                # print(s[i:j])  # 打印所有子串,会有空字符串
                substr = s[i:j]
                substr_len = len(substr)
                if len(set(substr)) == substr_len & substr_len > max_len:
                    max_len = substr_len
        return max_len

    @staticmethod
    def lengthOfLongestSubstring2(s: str) -> int:
        # 通过滑动窗口的方式优化
        # 滑动窗口:使用两个指针 left 和 right 来表示当前窗口的左右边界。
        max_len, left, right = 0, 0, 0
        tmp = []
        while (right < len(s)):
            # right从0开始,出现重复时停止,此时left开始右移并删除字符,直至重复的字符位置
            if s[right] not in tmp:
                tmp.append(s[right])
                right += 1
            else: # 逐次删字符,应该能再优化
                tmp.remove(s[left])
                left += 1
            max_len = max(len(tmp), max_len)
        return max_len

    @staticmethod
    def lengthOfLongestSubstring3(s: str) -> int:
        max_len, left = 0, 0
        tmp = {}  # { char1: 0, char2: 2, ... },存字符出现的索引
        for right, char in enumerate(s):
            # 当出现重复时,left=字符索引位置右移1个字符
            # tmp[char] >= left,确保left不会超过right
            if char in tmp and tmp[char] >= left:
                left = tmp[char] + 1
            tmp[char] = right  # 每次遍历都更新字符对应的索引
            max_len = max(max_len, right - left + 1)
        return max_len


if __name__ == "__main__":
    s = "abba"
    print(Solution.lengthOfLongestSubstring3(s))