‘’’
leetcode-3 无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
思路:
-
暴力法
假设我们有一个函数 boolean allUnique(String substring) ,如果子字符串中的字符都是唯一的,它会返回 true,否则会返回 false。
我们可以遍历给定字符串 s 的所有可能的子字符串并调用函数 allUnique。 如果事实证明返回值为 true,那么我们将会更新无重复字符子串的最大长度的答案。 -
滑动窗口法
在暴力法中,需要对所有子串序列就行判断是否有重复的字符。实际上一个子串 S[i,j-1] 是无重复的,那么只需要判断 S[j] 是否在 S[i,j-1]中出现过即可
那么就设定两个指针确定窗口,每次都判断尾指针的字符是否出现在了窗口内容,如果没有尾指针向后移动,如果有,那么就需要头指针向前走一步,重新开始滑动 -
滑动窗口法的优化:
在滑动窗口法中,如果尾指针已经在窗口内出现了,这个时候头指针只需要移动到尾指针在窗口内出现的位置的后一个即可,不能设置在尾指针之后
因为如果头指针向前走一步,尾指针在从头开始,那么之前滑动的窗口还需要在滑动一遍,最长长度还会比刚才的窗口少1
举例
ABCDC****
设置头指针A,尾指针A,字符位置字典{}
尾指针向后移动:
A 字符位置字典 A:0
B 字符位置字典 A:0,B:1
C 字符位置字典 A:0,B:1,C:2
D 字符位置字典 A:0,B:1,C:2,D:3
C 字符位置字典 A:0,B:1,C:4,D:3
此时C已经出现过了,那么就需要更新当前的字符位置,当前最长就是ABCD
下一个移动的时候头指针移动到D上,尾指针继续移动,
因为头指针移动到B C 是没有意义的,移动到B不会比现在的这个子串长度长
然后从当前尾指针没有出现过的位置重新开始计算长度
代码:
class Solution(object):
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
record = dict()#记录每个字母最后一次出现的下标,key是字母,val是下标
res, start = 0, 0
for end in range(len(s)):
if s[end] in record:#出现过
start = max(start, record[s[end]] + 1)
# 从尾指针上一次出现过的位置的后一个开始,从上一个位置之后的第一个位置到当前尾指针之间都是不同的字符
record[s[end]] = end #刷新最新下标
res = max(res, end - start + 1) #刷新res
return res

本文详细解析LeetCode第3题“无重复字符的最长子串”,介绍暴力法和滑动窗口法两种解题策略,重点阐述滑动窗口法的优化技巧及其实现代码。
2387

被折叠的 条评论
为什么被折叠?



