给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n) 的算法解决此问题。
示例 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
提示:
0 <= nums.length <= 105
-109 <= nums[i] <= 109
解法一:哈希表存放右边界
class Solution {
//哈希表记录当前数的右边界
public int longestConsecutive(int[] nums) {
Map<Integer,Integer> map = new HashMap<>();
//先存入自身的值
for (int num : nums) map.put(num,num);
int res = 0;
for (int num : nums) {
if (map.containsKey(num)) {
int right = map.get(num);
while (map.containsKey(right + 1)) {
//这步很重要,当right+1存在时,我们就把right的键值对删除,后面就可以判断right的key值不存在跳出循环,保证每个数只被遍历一次保证On
map.remove(right);
right = map.get(right+1);
}
res = Math.max(res,right - num + 1);
map.put(num,right);
}
}
return res;
}
}
解法二:哈希表存放连续区间长度
class Solution {
//哈希表记录当前数的连续区间长度
public int longestConsecutive(int[] nums) {
Map<Integer,Integer> map = new HashMap<>();
int res = 0;
for (int num : nums) {
//只有当哈希表里面没有的数我们才统计
if (!map.containsKey(num)) {
//左连续区间和右连续区间,因为num未存在哈希表中,所以key=num-1,它的value表示区间只能是[num-value,num-1],同理key=num+1,它的value表示区间只能是[num+1,num+value];
int left = map.getOrDefault(num-1,0);
int right = map.getOrDefault(num+1,0);
int curLen = left + right + 1;
res = Math.max(res,curLen);
//标记num,可以put任意值,如果[left,num]会put num,成为右边界,[num,right],会put num,成为左边界,否则则会成为中间值[left,right];
map.put(num,-1);
map.put(num-left,curLen);
map.put(num+right,curLen);
}
}
return res;
}
}
解法三:并查集
class Solution {
Map<Integer,Integer> map = new HashMap<>();
private int find(int x) {
if (!map.containsKey(x)) return 0x3f3f3f3f;
//路径压缩
if (map.get(x) != x) map.put(x,find(map.get(x)));
x = map.get(x);
return x;
}
private void union(int x, int y) {
int a = find(x);
int b = find(y);
if (a == b) return;
map.put(a,b);
}
public int longestConsecutive(int[] nums) {
for (int num : nums) map.put(num,num);
for (int num : nums) {
if (find(num+1) != 0x3f3f3f3f)
union(num,num+1);
}
int res = 0;
for (int num : nums)
res = Math.max(res,find(num) - num + 1);
return res;
}
}