小知识,大挑战!本文正在参与“程序员必备小知识”创作活动
本文同时参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金
最长无重复子数组
问题描述
给定一个数组arr,返回arr的最长无重复元素子数组的长度,无重复指的是所有数字都不相同。子数组是连续的,比如[1,3,5,7,9]的子数组有[1,3],[3,5,7]等等,但是[1,3,7]不是子数组。
示例
输入:[2,2,3,4,8,99,3]
返回值:5
说明:[2,3,4,8,99]是最长子数组
分析问题
在开始之前,我们首先介绍一下什么是滑动窗口。顾名思义,所谓的滑动窗口就是可以在一个序列上进行滑动的窗口。如图所示,假设,我们的序列为abcabcbb,我们这里定义了一个固定大小为3的窗口在序列上滑来滑去。

在实际的使用中,我们使用的滑动窗口都是可变长度的。
我们可以使用双指针来维护窗口的开始和结束,通过移动左、右指针来实现窗口大小的改变和窗口的滑动。
我们来看一下题目,题目是求最长无重复元素子数组,如果我们可以求出所有的无重复元素的子数组,那取出最长的不就好了。下面我们来看一下如何求解。我们只需要维护一个在数组中进行滑动的窗口就好。
- 开始时2不在窗口中,所以扩大窗口。
- 下一个元素2在窗口中出现,所以我们要将出现过的元素及其左边的元素统统移出窗口,即2。
- 接下来的元素3、4、8、99都没在窗口中出现过,所有我们把它们都加入到窗口中。
- 下一个元素3在窗口出现过,所以我们要移除出现过的元素及其左边的元素,即2,3。
下面我们来看一下代码如何实现。
if not s:
return 0
left = 0
# 记录每个字符是否出现过
window = set()
n = len(s)
max_len = 0
for i in range(n):
#如果出现过,移除重复元素及其左边的元素
while s[i] in window:
window.remove(s[left])
left += 1
#没出现过,加入window
window.add(s[i])
max_len = max(len(window),max_len)
return max_len
时间复杂度是O(n)。