LeetCode 热题 HOT 100 Java题解
128. 最长连续序列
题目:
给定一个未排序的整数数组,找出最长连续序列的长度。
要求算法的时间复杂度为 O ( n ) O(n) O(n)。
示例:
输入: [100, 4, 200, 1, 3, 2]
输出: 4
解释: 最长连续序列是 [1, 2, 3, 4]。它的长度为 4。
哈希表+动态规划
本题目要求时间复杂度为 O ( n ) O(n) O(n),因此我们在遍历的过程中查找是否有与当前相连的数字需要用到哈希表,这样才能保证每次查找都是 O ( 1 ) O(1) O(1)复杂度,核心思想就是拿当前数字去找与其左右相连的数字集合看看能否组成一个更大的集合,并更新两端的最长值,过程中遇到哈希表中已存在的值就跳过,并且维护一个最大值用于返回。
import java.util.HashMap;
import java.util.Map;
class Solution {
public int longestConsecutive(int[] nums) {
Map<Integer, Integer> map = new HashMap<>();
int max = 0;
for (int i = 0; i < nums.length; i++) {
if (map.containsKey(nums[i])) continue;
int left = map.getOrDefault(nums[i] - 1, 0);
int right = map.getOrDefault(nums[i] + 1, 0);
int len = left + right + 1;
max = Math.max(max, len);
map.put(nums[i], len);
map.put(nums[i] - left, len);
map.put(nums[i] + right, len);
}
return max;
}
}
复杂度分析
-
时间复杂度: O ( n ) O(n) O(n)
遍历一次。
-
空间复杂度: O ( n ) O(n) O(n)
哈希表额外空间 O ( n ) O(n) O(n)。
并查集
使用并查集的思想比较简单,将相邻的数字合并起来,然后再遍历一遍记录最大值即可。
import java.util.HashMap;
import java.util.Map;
class Solution {
class UnionFind{
Map<Integer, Integer> parents;
public UnionFind(int[] arr) {
parents = new HashMap<>();
for (int i : arr) {
parents.put(i, i);
}
}
public Integer find(int x) {
if (!parents.containsKey(x)) return null;
int t = parents.get(x);
if(x != t) parents.put(x, find(t));
return parents.get(x);
}
public boolean union(int x, int y) {
Integer rootX = find(x), rootY = find(y);
if (rootX == null || rootY == null) return false;
if(rootX.equals(rootY)) return false;
parents.put(rootX, rootY);
return true;
}
}
public int longestConsecutive(int[] nums) {
if (nums.length == 0) return 0;
UnionFind u = new UnionFind(nums);
for (int num : nums) {
u.union(num, num + 1);
}
int max = 1;
for (int num : nums) {
max = Math.max(max,u.find(num) - num + 1);
}
return max;
}
}
复杂度分析
-
时间复杂度: O ( n ) O(n) O(n)
遍历一次。
-
空间复杂度: O ( n ) O(n) O(n)
并查集额外空间 O ( n ) O(n) O(n)。