题目
给定一个未排序的整数数组 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
解法
解法1 TreeSet保存
- 第一遍遍历数组,将数组元素分别加入一个不重复有序Set(TreeSet)中;
- 第二遍遍历数组,遍历得出最长的连续序列长度。
class Solution {
public int longestConsecutive(int[] nums) {
if (nums.length <= 1) return nums.length;
// 初始化set
Set<Integer> set = new TreeSet<>();
for (int num : nums) {
set.add(num);
}
// 遍历找出最长连续序列长度
Integer prev = null;
int currentLength = 1;
int maxLength = 1;
for (Integer num : set) {
if (prev != null) {
if (num == prev + 1) {
currentLength++;
} else {
maxLength = Math.max(maxLength, currentLength);
currentLength = 1;
}
}
prev = num;
}
maxLength = Math.max(maxLength, currentLength);
return maxLength;
}
}
将长度为N的数组插入TreeSet的时间复杂度为O(NlogN)
,不符合题目中的时间复杂度要求。
解法2 找连续序列头部
- 第一次遍历,将数组nums依次加入
HashSet()
- 遍历set,若该数值-1的数不在set中存在,则说明该元素是一个连续序列的开头,往后依次查找,每查到一个就currentLength++,
并将该元素从set移除。
class Solution {
public int longestConsecutive(int[] nums) {
// 将元素放入一个hash表中,提高查询效率
Set<Integer> set = new HashSet<>();
for (int num : nums)
set.add(num);
// 遍历找到最长序列长队
int maxLength = 0;
for (int num : set) {
if (set.contains(num - 1))
// 说明不是一个连续序列的起始位置
continue;
int currentLength = 1;
while (set.contains(++num))
currentLength++;
maxLength = Math.max(maxLength, currentLength);
}
return maxLength;
}
}
时间复杂度为O(N)
无效改进 – 用HashMap实现,将遍历过的标记,以后节省时间😓
class Solution {
public int longestConsecutive(int[] nums) {
if (nums.length <= 1) return nums.length;
// 初始化HashSet
Map<Integer, Integer> map = new HashMap<>();
for (int num : nums) {
map.put(num, 0);
}
// 遍历set找长度
int maxLength = 1;
int currentLength = 1;
Set<Integer> keys = map.keySet();
for (Integer num : keys) {
if (map.get(num) == 1) continue;
if (!map.containsKey(num - 1)) {
while (map.containsKey(num + 1)) {
currentLength++;
num++;
map.put(num, 1);
}
maxLength = Math.max(currentLength, maxLength);
currentLength = 1;
}
}
return maxLength;
}
}
结果并没有减少用时,反而增加了😭。
原因是还是会进入循环做map.get(num) == 1的判断,并没有节省操作,反而因为多余的map.put
增加了多余操作。
小结
数组的查找效率比较慢,而Hash表(HashSet、HashMap)的查找复杂度为O(1)
,本题中因为要求时间复杂度优化到O(n)
,明显不能用排序【最好也要O(NlogN)
】,所以可以考虑效率更高地进行查找,也就是选择HashSet、HashMap这类数据结构。
- 0911
- 0918
- 0925