问题:给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
题目来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters
难度:中等
分析:求子串=>滑动窗口法,求无重复=>哈希表。
这道题的本质是维护一个滑动窗口寻找子串,优化方法是维护这个窗口的方法不同。
解决方法:
1:滑动窗口法+数组
class Solution():
def lengthOfLongestSubstring(self,s):
window = [] #维护一个滑动窗口
max_length = 0 #最长子串长度
for c in s:#遍历字符串
if c not in window:#如果新取的字符不在滑窗内
window.append(c)#加入滑窗中
else:#如果新取的字符在滑窗内,说明字串字符开始重复
window[:] = window[window.index(c)+1:]#把滑窗移动到重复字符的后一位
window.append(c)#把新取的字符加入滑窗
max_length = max(len(window),max_length)#更新最长字串长度
return max_length
复杂度:O(n)
2:滑动窗口法+双指针
class Solution():
def lengthOfLongestSubstring(self,s):
max_length = 0 #最长子串长度
left, right = 0,0 #维护左右两个指针,双指针组成个滑窗
for c in s: #遍历字符串
if c not in s[left:right]: #如果字符不在字符串中
right = right + 1 #右指针向右移一位,把字符加入滑窗中
else: #如果字符在字符串中,说明子串中的字符开始重复
left += s[left:right].index(c) + 1 #左指针移动到重复的字符的后一位
right = right + 1 #右指针向右移动一位,把字符加入其中
max_length =max(max_length,right - left) #更新最长字符串长度
return max_length
复杂度:O(n)
2:滑动窗口法
class Solution():
def lengthOfLongestSubstring(self,s):
#由哈希表来维护一个窗口,思路跟前两种方法稍有不同
ignore_end = -1 #要丢掉的滑窗走过的字符串的末位
hashMap = {} #构造哈希表
max_length = 0 #最长字串长度
for i,c in enumerate(s): #遍历数组
if c in hashMap and hashMap[c]> ignore_end:
#如果字符在哈希表中,说明子串开始重复
#要保证判断重复的字符是在滑窗内的,
#所以要判断下与新字符重复的字符在哈希表中的位置
ignore_end = hashMap[c] #字符重复,则滑窗滑到不重复的部分,更新要删掉的位置末尾
hashMap[c] = i #新字符加入哈希表中,与之前重复也没关系,重复的都被丢掉了
#所以不用考虑哈希冲突
else:
hashMap[c] = i #新字符加入哈希表
max_length = max(max_length,i-ignore_end) #更新最长子串长
return max_length
复杂度:O(n)
三种方法的"术"是相同的(都是滑动窗口),差别在"技"上 - 1.容器 2.指针 3.Hash
方法1中容器的伸缩涉及内存分配,所以方法2换成位置指针省掉了内存分配
方法2位置指针还是要扫描重复字符,所以方法3用Hash直接判断省掉了扫描开销.
题解思路来自:imckl
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/python-hua-dong-chuang-kou-xun-xu-jian-jin-de-3ge-/