无重复字符的最长子串
给定一个字符串 s
,请你找出其中不含有重复字符的最长子串的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc"
,所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b"
,所以其长度为 1。
示例 3:
输入: s = "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是"wke"
,所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke"
是一个子序列,不是子串。
提示:
0 <= s.length <= 5 * 10e4
s
由英文字母、数字、符号和空格组成
这道题目先想到的是逐个循环呗...最后发现竟然没有超时,应该是测试样例卡的不严,要不然肯定会超了... 时间复杂度也是来到了o(n²)
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if len(s) == 1 or len(s) == 0:return len(s)
res = 0
for i in range(len(s)):
hashmap = {s[i]:1}
for j in range(i+1,len(s)):
if s[j] in hashmap:break
else:
hashmap[s[j]] = 1
res = len(hashmap.keys()) if res<len(hashmap.keys()) else res
return res
那这道题目应该是要用滑动窗口来做,但是之前不太懂,今天学一下。
———————————————————————————————————————————
用滑动窗口其实就是跳越左边的边界,让左边的边界跳到合适的地方,而这个合适的地方其实就是与他重复的元素的索引位置
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
hashmap = {}
left = -1
res = 0
for i in range(len(s)):
if s[i] in hashmap:left = max(hashmap[s[i]],left)# 这一步是关键 左指针和res都是用max来走值
hashmap[s[i]] = i
res = max(i-left,res)
return res
最重要的其实是左指针和res的赋值部分,用max函数,特别是left,用max函数防止left左移动,保证left要一直往右移动
———————————————————————————————————————————
more:下午又做了一遍,发现还是写的有问题,不扎实,遂再拜题解,加深印象,终于知新。
滑动窗口的方法其实是拿着一个容器,不断修改左右边界来帮助解题目的方法。
而之前最不明白的地方其实是left为什么= -1,看了一些大佬的题解之后,才知道如果left=0,right也=0,则相当于滑动窗口初始化的容量是1了,所以left应该是 -1,至于我写的时候容易把left初始化为0,导致怎么修改都不对。
考虑一种最简单的情况,abca,a b c 的时候均将元素放到hashmap中,value分别=0,1,2,等到了第二个a的时候,此时发现有重复了。注意!这里非常重要的顺序,即发现有重复元素,随后要修改left的值,使得滑动窗口锁死,然后更新hashmap[s[right]]的值,然后再计算res
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
right = 0
left = -1
hm = {}
res = 0
for right in range(len(s)):
if s[right] in hm:
left = max(left,hm[s[right]])
res = max(res,right-left)
hm[s[right]] = right
return res