给定一个未排序的整数数组
nums,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为O(n)的算法解决此问题。
样例
Example
示例 1:
**输入:**nums = [100,4,200,1,3,2]
**输出:**4
**解释:**最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。示例 2:
**输入:**nums = [0,3,7,2,5,8,4,6,0,1]
**输出:**9示例 3:
**输入:**nums = [1,0,1,2]
**输出:**3提示:
0 <= nums.length <= 105-109 <= nums[i] <= 109
思路
- 方法一:先考虑朴素解法,遍历每一个数,再依次在数组里找有没有下一个数,直到遍历完整个数组。但是这样时间复杂度肯定爆炸了。要想快速知道下一个数有没有,可以先预处理把全部数都存在一个Set里,这样就能快速的找到后面的数了。假如输入是一个以1递增的数组,每个数都要一直数到最后,显然还是O(N
- 方法二:先看示例
[100,4,200,1,3,2],逐个遍历:[[100]],[[4]、[100]],[[4]、[100, 200]],[[1]、[4]、[100, 200]],[[1]、[3, 4]、[100, 200]],[[1, 2, 3, 4]、[100, 200]]。最后得到4。可以发现我们是在不断地序列连起来,从而得到最长序列。因此我们需要知道一个数前和后的最长序列长度,然后计算head + 1 + tail就是序列长度了,又因为最大长度更新只会发生在头尾相连时,因此只需要更新序列头尾的长度就能得到结果。需要注意要进行去重,序列中间的长度不会被更新,再次计算可能会导致错误的结果。
答案
Java
// 方法一
class Solution {
public int longestConsecutive(int[] nums) {
Set<Integer> set = new HashSet<>();
int ans = 0;
for (int num : nums) {
set.add(num);
}
for (int num : set) {
if (set.contains(num - 1)) {
continue;
}
int cnt = 1;
while (true) {
if(!set.contains(num + cnt)){
break;
}
cnt++;
}
ans = Math.max(ans, cnt);
}
return ans;
}
}
// 方法二
class Solution {
public int longestConsecutive(int[] nums) {
Map<Integer, Integer> map = new HashMap<>();
int ans = 0;
for (int num : nums) {
if (map.containsKey(num)) {
continue;
}
int head = map.getOrDefault(num - 1, 0);
int tail = map.getOrDefault(num + 1, 0);
int length = head + 1 + tail;
ans = Math.max(ans, length);
map.putIfAbsent(num, 1);
map.put(num - head, length);
map.put(num + tail, length);
}
return ans;
}
}