无重复字符的最长子串 滑动窗口
题目描述:
给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
示例 4:
输入: s = ""
输出: 0
思路分析
题目中已经提示了是“子串”而非“子序列”了,所以这是一道典型的滑动窗口问题。
滑动窗口算是一个模板级别的解题思路,如果初次接触,可以先根据我的注释来领会,后面应该还会有用滑动窗口解决的问题,接触多了就会发现其实都差不太多。在这里推荐一下《labuladong的算法小抄》,里面不止对滑动窗口的模板有很好的归纳,还有很多其他常见的解题思路讲解,我看完过整本书,虽然还没有全部掌握,但收益良多。
对于这道题,我先简单描述一下使用滑动窗口的思路。首先我们需要在给定的字符串上面开一个“窗口”,初始就大小为1,即一个左边界在下标0处、右边界也在下标0处的一个“区间”。接着我们逐步扩大右边界(右边界向右移动,保持左边界不变),扩大的同时判断窗口当前覆盖的范围是否满足字符无重复条件:若满足,就可以继续扩大,每次扩大的同时就可以更新我们的最长长度;若不满足,则开始缩小左边界(左边界向右移动,右边界不变),直到缩小至窗口内的字符串满足字符无重复条件。收缩结束后,也去比较和更新最终长度结果。
代码:
class Solution(object):
def lengthOfLongestSubstring(self,s):
"""
:type s: str
:rtype: int
"""
dic = {}
#dic的作用是保存记录当前窗口内包含的字符个数
#比如若当前窗口内为“absa”,则dic={a:2,b:1,s:1}
right=0#窗口右边界
left=0#窗口左边界
lenth = len(s)
res = 0
def tianjia(dic,a):
#在字典dic中添加元素a,若存在则+1,不存在则初始化为1
#定义这样一个工具函数,后面写起来会更清晰一点
if a not in dic:
dic[a]=1
else:
dic[a]+=1
#判断字典合法性函数,即值有大于1的,则说明有重复,不合法
#这里的合法指满足题目要求无重复字符
def hefa(dic):
for v in dic.values():
if v>1:
return False
return True
#开始正式滑动窗口
while right<lenth:#限定right不能超过数组长度
c = s[right]#取出right的当前值
right+=1#right向右扩张
tianjia(dic,c)#把当前值存入字典,字典里的元素就是当前“窗口”中的元素
while not hefa(dic):#第二层wihle,当窗口内不合法时,要开始收缩左窗口
c=s[left]#把左边界的值取出
dic[c]-=1#字典中对应字母数量-1
left+=1#左窗口收缩
res = max(res,right-left)#没收缩或者收缩结束后,尝试更新res为最大
return res
总结一下,可以通过这道题打开滑动窗口的大门,把滑动窗口摸清了,以后再看见其实就是默写和熟练度的问题了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了