128. 最长连续序列
20200606
难度:困难
题目描述
给定一个未排序的整数数组,找出最长连续序列的长度。
要求算法的时间复杂度为 O(n)。
示例:
输入: [100, 4, 200, 1, 3, 2]
输出: 4
解释: 最长连续序列是 [1, 2, 3, 4]。它的长度为 4。
Solution
方法一
排序+比较
- 先从小到大排序
- 遍历数组,比较相邻的两项,如果相同,则跳过,继续遍历下一项
- 如果 前一项+1 等于当前项,说明遇到连续项,cur +1
- 否则,说明连续中断,将 cur重置为 1
class Solution {
public int longestConsecutive(int[] nums) {
if(nums == null || nums.length == 0) return 0;
Arrays.sort(nums);
int max = 1;
int cur = 1;
for(int i = 1; i < nums.length; i++){
if(nums[i] != nums[i-1]){
if(nums[i-1] + 1 == nums[i]){
cur++;
}else{
max = Math.max(max, cur);
cur = 1;
}
}
}
return Math.max(cur, max);
}
}
方法二
HashSet
class Solution {
public int longestConsecutive(int[] nums) {
Set<Integer> set = new HashSet<>();
for(int num : nums){
set.add(num);
}
int max = 0;
for(int num : set){
if(!set.contains(num - 1)){
int curNum = num;
int curStreak = 1;
while(set.contains(curNum + 1)){
curStreak++;
curNum++;
}
max = Math.max(max, curStreak);
}
}
return max;
}
}
方法三
并查集UnionFind
- max:记录节点集合的最大值
- fatherMap:记录每个节点的父亲
- sizeMap:记录每个节点所在集合的大小
class Solution {
public int longestConsecutive(int[] nums) {
if(nums == null || nums.length == 0) return 0;
UnionFind uf = new UnionFind(nums);
for(int i = 0; i < nums.length; i++){
// 查看当前节点的上一节点是否在nums中
if(uf.fatherMap.containsKey(nums[i]-1)){
uf.union(nums[i]-1, nums[i]);
}
}
return uf.max;
}
public class UnionFind{
int max = 1;
HashMap<Integer, Integer> fatherMap;
HashMap<Integer, Integer> sizeMap;
public UnionFind(int[] nums){
fatherMap = new HashMap<>();
sizeMap = new HashMap<>();
// 初始化UnionFind,将所有节点指向自己,所有节点的size为1
for(int val : nums){
fatherMap.put(val, val);
sizeMap.put(val, 1);
}
}
//找到父节点并优化结构
public int findFather(int val){
int father = fatherMap.get(val);
if(father != val){
father = findFather(father);
}
fatherMap.put(val, father);
return father;
}
public void union(int a, int b){
int aFather = findFather(a);
int bFather = findFather(b);
if(aFather != bFather){
int aFatherSize = sizeMap.get(aFather);
int bFatherSize = sizeMap.get(bFather);
//将bF作为aF的父亲
fatherMap.put(aFather, bFather);
sizeMap.put(bFather,aFatherSize + bFatherSize);
max = Math.max(max, aFatherSize + bFatherSize);
}
}
}
}
并查集相应的题目:
- 128.最长连续序列 48.2% 困难
- 130.被围绕的区域 39.7% 中等
- 200.岛屿数量 47.6% 中等
- 547.朋友圈 55.5% 中等
- 721.账户合并 32.5% 中等
- 839.相似字符串组 31.9% 困难