打败算法 —— 无重复字符的最长子串

本文参考

出自LeetCode上的题库 —— 无重复字符的最长子串,本题又是滑动窗口的一次应用

https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/

无重复字符的最长字串问题

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

返回滑动窗口每次移动后,窗口中的最大值

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

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

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

解题思路

之前做到过和本题类似的题目"最小覆盖字串"(https://www.cnblogs.com/kuluo/p/15945437.html),仍然按照滑动窗口的基本思路,当窗口内的子字符串始终满足"不重复"的要求时,右指针一直向右移动,直到窗口内的子字符串出现重复字符

在"最小覆盖字串"中,我们就已经发现,如果左指针每次只移动一个距离,会浪费很多的循环,我们让左指针直接跳转到特定位置,满足窗口内的要求。在本题中,可以让左指针直接移动到重复字符第一次出现时的下一个位置上

滑动窗口解法

class Solution:
  def length_of_longest_substring(self, s: str) -> int:
    left = 0
    right = 1
    ans = 0
    while right <= len(s):
      sub_str = s[left:right]
      # 判断窗口中是否有重复字符 

      step = self.step(sub_str)
      if step:
        left += step
      else:
        ans = ans if ans >= len(sub_str) else len(sub_str)
        right += 1
    return ans

  def step(self, s: str) -> int:
    # 记录子串中各个字符出现的位置 

    rel = dict()
    for i in range(len(s)):
      c = s[i]
      if c in rel.keys():
        # 返回需要让左指针跳转的步长 

        return rel[c] + 1
      else:
        rel[c] = i
    return 0

posted @ 2022-03-12 10:34  咕~咕咕  阅读(39)  评论(0编辑  收藏  举报