1.思路
我们来找找规律,先从暴力的思路,从每一个元素开始的,不包含重复元素的最长序列,那么其中最长的那个子序列即为答案。我们发现依次递增地枚举子序列的起始位置,那么子序列的结束位置也是递增的!
那我们发现了这个规律之后,怎么能优化这道题的复杂度呢?这里就要用到双指针算法。用左右指针维护最长子序列。
2.代码
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[] a = new int[n];
for(int i = 0; i < n; i++)
a[i] = in.nextInt();
Map<Integer, Integer> map =new HashMap<>(); //保存数组元素和下标
int l = 0, ans = 0; //左指针
for(int r = 0; r < n; r++) { //遍历右指针
//如果右指针发现当前元素在哈希表中已经出现,就看要不要更新左指针的位置
//如果左指针比出现在哈希表的元素的位置+1小,就把左指针移到哈希表的元素的位置+1,这样使得逻辑上删除了前面的元素,并且没有重复元素,但是实际上没删
//如果左指针比出现在哈希表的元素的位置+1大,就代表右指针指向的元素在逻辑上已经被删除
if(map.containsKey(a[r]))
l = Math.max(l, map.get(a[r]) + 1);
//如果当前字符在哈希表中不存在,那就直接加入表中;如果当前字符存在,就覆盖之前在哈希表中的字符,并且更新了坐标
map.put(a[r], r);
//计算最长连续子序列
ans = Math.max(ans, r - l + 1);
}
System.out.println(ans);
}
}
3.复杂度分析
- 时间复杂度:O(n)
- 空间复杂度:O(n)