LeetCode 刷题小本本Day4 Longest Substring Without Repeating Characters(滑动窗口)

题目

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

我的答案:

class Solution:
    def lengthOfLongestSubstring(self, s:str):
        res_max = 0
        for iter in range(len(s)):
            max_len = []
            for i in range(len(s)-iter):
                if s[i+iter] not in (max_len):
                    max_len.append(s[i+iter])
                else:
                    break
                res_max = max(res_max,len(max_len))
        return res_max

用的是笨笨的办法,弄了两次循环,时间复杂度很高,时间消耗就超级大了~
看了一下参考答案,都提到了“滑动窗口”。即:保证那一个窗口内的字符都是唯一的。

滑动窗口:

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        # 哈希集合,记录每个字符是否出现过
        occ = set()
        n = len(s)
        # 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
        rk, ans = -1, 0
        for i in range(n):
            if i != 0:
                # 左指针向右移动一格,移除一个字符
                occ.remove(s[i - 1])
            while rk + 1 < n and s[rk + 1] not in occ:
                # 没有重复值,就不断地移动右指针
                occ.add(s[rk + 1])
                rk += 1
            # 第 i 到 rk 个字符是一个极长的无重复字符子串
            ans = max(ans, rk - i + 1)
        return ans
  • 设定左指针和右指针,一开始固定左指针,不断移动右指针,直到有重复字符出现。
  • 一轮下来,左指针往右移一格,再来一次。
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        if not s:return 0
        left = 0
        lookup = set()
        n = len(s)
        max_len = 0
        cur_len = 0
        for i in range(n):
            cur_len += 1
            while s[i] in lookup:
                lookup.remove(s[left])
                left += 1
                cur_len -= 1
            if cur_len > max_len:max_len = cur_len
            lookup.add(s[i])
        return max_len

思路和前面那个差不多~

参考答案 2:

class Solution:
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        st = {}
        i, ans = 0, 0
        for j in range(len(s)):
            if s[j] in st:
                i = max(st[s[j]], i) # i代表起始位置
            ans = max(ans, j - i + 1)
            st[s[j]] = j + 1
        return ans
  • j 表示子串终止位置,i表示字串起始位置。
  • 当未出现重复时,字符串的长度即为字符串的结束位置减去起始位置。
  • 发生重复时,重新利用字符串的结束位置j减去新的起始位置i,并与之前的未重复字串的长度作比较取较大者。

这个方法很巧妙,可是我学不太会,还是滑动窗口更好理解一些~

知识

  1. set()移出指定元素用remove(),无返回值。
  2. 滑动窗口的思想。没有重复字符时调整右窗口,出现重复字符后调整左窗口。

你可能感兴趣的:(LeetCode,leetcode,算法,职场和发展)