并查集
维护一个树节点个数的map
class Solution {
class UnionFind {
// 记录每个节点的父节点
private Map<Integer, Integer> parent;
// 记录节点树的节点个数
private Map<Integer, Integer> count;
public UnionFind(int[] nums) {
parent = new HashMap<>();
count = new HashMap<>();
// 初始化父节点为自身
for (int num : nums) {
parent.put(num, num);
count.put(num, 1);
}
}
// 寻找x的父节点,实际上也就是x的最远连续右边界
public Integer find(int x) {
if (!parent.containsKey(x)) {
return null;
}
// 遍历找到x的父节点
while (x != parent.get(x)) {
// 进行路径压缩
parent.put(x, parent.get(parent.get(x)));
x = parent.get(x);
}
return x;
}
// 合并两个连通分量,用来将num并入到num+1的连续区间中
// 返回值为x所在连通分量的节点个数
public int union(int x, int y) {
int rootX = find(x);
int rootY = find(y);
if (rootX == rootY) {
return count.get(rootX);
}
parent.put(rootX, rootY);
// 更新该根结点连通分量的节点个数
count.put(rootY, count.get(rootX) + count.get(rootY));
return count.get(rootY);
}
}
public int longestConsecutive(int[] nums) {
// 去除nums为空的特例
if (nums == null || nums.length == 0) {
return 0;
}
UnionFind uf = new UnionFind(nums);
int ans = 1;
// 一次遍历即可
for (int num : nums) {
if (uf.find(num + 1) != null) {
// union会返回num所在连通分量的节点个数
ans = Math.max(ans, uf.union(num, num + 1));
}
}
return ans;
}
}
hash
找到每个序列最左侧的节点开始找到完整的链
class Solution {
public int longestConsecutive(int[] nums) {
// key表示num,value表示num最远到达的连续右边界
Map<Integer, Integer> map = new HashMap<>();
// 初始化每个num的右边界为自己
for (int num : nums) {
map.put(num, num);
}
int ans = 0;
for (int num : nums) {
if (!map.containsKey(num - 1)) {
int right = map.get(num);
// 遍历得到最远的右边界
while (map.containsKey(right + 1)) {
right = map.get(right + 1);
}
// 更新右边界
map.put(num, right);
// 更新答案
ans = Math.max(ans, right - num + 1);
}
}
return ans;
}
}