Given an unsorted array of integers, find the length of the longest consecutive elements sequence.
For example,
Given [100, 4, 200, 1, 3, 2]
,
The longest consecutive elements sequence is [1, 2, 3, 4]
. Return its length: 4
.
Your algorithm should run in O(n) complexity.
The Union Find way:
We could use a hashmap to apply union find, once comes in a new number i , we connect i with (i - 1) and (i + 1) if they already exist in the union find. And we should always ensure that the root is the smallest number in the consecutive sequence.
Code:
public class Solution {
public int longestConsecutive(int[] nums) {
HashMap<Integer,Integer> uf = new HashMap();
for(int i : nums){
if(!uf.containsKey(i)){
uf.put(i,i);
if(uf.containsKey(i + 1)){
union(uf,i,i+1);
}
if(uf.containsKey(i - 1)){
union(uf,i-1,i);
}
}
}
int len = 0;
for(int key : new HashSet<Integer>(uf.keySet())){
int pre = findRoot(uf,key);
len = Math.max((key - pre + 1), len);
}
return len;
}
int findRoot(HashMap<Integer,Integer> uf, int x){
if(uf.containsKey(x)){
if(uf.get(x) != x){
int ans = findRoot(uf,uf.get(x));
uf.put(x,ans);
return ans;
}
}
return x;
}
void union(HashMap<Integer,Integer> uf, int x, int y){
int r1 = findRoot(uf,x);
int r2 = findRoot(uf,y);
if(r1 > r2){
uf.put(r1,r2);
} else {
uf.put(r2,r1);
}
}
}
Another way to do it is to convert the array to a set, for each number i , if i is the start of the sequence( (i - 1) not in the set), count the length of the sequence starting at i, otherwise continue.
Code:
public class Solution {
public int longestConsecutive(int[] nums) {
HashSet<Integer> hs = new HashSet();
for(int i : nums){
hs.add(i);
}
int ret = 0;
for(int i : hs){
if(!hs.contains(i - 1)){
int c = 0;
while(hs.contains(i++)){
c++;
}
ret = Math.max(ret,c);
}
}
return ret;
}
}