LeetCode100-3无重复字符的最长子串(滑动窗口)

本文基于各个大佬的文章

上点关注下点赞,明天一定更灿烂!


前言

        Python基础好像会了又好像没会,所有我直接开始刷leetcode一边抄样例代码一边学习吧。本系列文章用来记录学习中的思考,写给自己看的,也欢迎大家在评论区指导~

        您的每一条评论都会让我更有学习的动力。


一、分析题目

补充:字串是字符串中连续的非空序列

本题目被划分到了【滑动窗口】分组

滑动窗口(Sliding Window)是一种基于双指针技术的高效算法,专门用于解决数组或字符串的子序列 / 子数组问题。它通过定义一个 "窗口" 来框定处理范围,并通过移动窗口来减少重复计算,从而优化时间复杂度。

分为固定大小窗口和可变大小窗口

滑动窗口与双指针的关系:滑动窗口是双指针技术的特殊应用

特性双指针技术滑动窗口技术
核心思想使用两个指针协同工作使用两个指针定义一个窗口
指针关系可以同向、相向或其他关系通常是同向,左指针 <= 右指针
应用范围广泛,包括数组、链表等主要用于数组 / 字符串的子序列问题
窗口概念不一定有明确窗口概念明确的窗口范围和滑动操作
典型应用两数之和、反转数组、环形链表子数组求和、最长子串、字符串匹配

滑动窗口技术适合解决的问题:

  1. 子序列 / 子数组问题:需要处理数组或字符串的连续部分
  2. 范围查询问题:需要在特定范围内进行计算或判断
  3. 重复计算问题:暴力解法中存在大量重复计算的问题
  4. 条件匹配问题:需要找到满足特定条件的子序列

滑动窗口算法的基本步骤

  1. 初始化窗口:定义左右指针,通常初始化为 0
  2. 扩展窗口:移动右指针,扩大窗口范围,直到满足特定条件
  3. 收缩窗口:在满足条件的情况下,尝试移动左指针,缩小窗口范围,优化结果
  4. 记录结果:在窗口滑动过程中记录满足条件的最优结果
  5. 滑动窗口:重复步骤 2-4,直到右指针到达数据末尾
    """
    初始化 left = 0, result = 初始值
    for right in 0..n-1:
        加入当前元素到窗口
        while 窗口满足条件:
            更新result
            移除左侧元素,移动left指针
    return result
    """

二、思路以及代码

因为字串是字符串中连续的非空序列,结合样例3

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

所以不能简单的在原有字符串的基础上做去重操作

因为最长字串的长度不一定为多少,所以这是一个可变长度窗口问题。

思路:

  1. 使用左右指针定义窗口范围,初始时左右指针都指向字符串开头
  2. 右指针右移扩大窗口,将字符加入窗口
  3. 使用哈希表记录每个字符最后出现的位置
  4. 如果遇到重复字符,将左指针移动到重复字符的下一个位置
  5. 不断更新最大窗口长度
right当前字符操作说明
0'a''a' 不在字典中,加入:char_index['a']=0最大子串变为 "a",长度1
1'b''b' 不在字典中,加入:char_index['b']=1子串 "ab",长度2
2'c''c' 不在字典中,加入:char_index['c']=2子串 "abc",长度3
3'a''a' 已在字典,位置0,且 >= left=0,表示重复

移动 left 到 0+1=1,为跳过第一个 'a'

更新 char_index['a']=3

计算最大长度:3 - 1 + 1=3

4'b''b' 在字典位置1 >= left=1,重复

left=1+1=2

更新 char_index['b']=4

计算最大长度:4 - 2 +1=3

5'c''c' 在字典位置2 >= left=2,重复

left=2+1=3

更新 char_index['c']=5

计算最大长度:5 - 3 +1=3

6'b''b' 在字典位置4 >= left=3

left=4+1=5

更新 char_index['b']=6

计算最大长度:6 - 5 +1=2

7'b''b' 在字典位置6 >= left=5

left=6+1=7

更新 char_index['b']=7

计算最大长度:7 - 7 +1=1

最后,最长不重复子串长度为 3。

    class Solution:
        def lengthOfLongestSubstring(self, s: str) -> int:
            # 初始化左指针和最大长度
            left = 0
            max_length = 0
            # 创建空哈希表(字典),用于记录字符最后出现的位置
            char_index = {}
            
            # 右指针遍历字符串
            for right in range(len(s)):
                current_char = s[right]
                
                # 如果字符已在当前窗口中出现,移动左指针到重复字符的下一个位置
                if current_char in char_index and char_index[current_char] >= left:
                    left = char_index[current_char] + 1
                
                # 更新字符最后出现的位置
                char_index[current_char] = right
                
                # 更新最大长度
                current_length = right - left + 1
                if current_length > max_length:
                    max_length = current_length
            
            return max_length

    运行一下,啦啦啦

    三、本题收获

    学习了双指针的进阶用法,而且也算是复习了哈希表


    总结

            只会打暴力,基础一团糟,明天再学吧老铁,别真学会了。

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值