一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第22天,点击查看活动详情。
一、题目 leetcode 最长连续序列
给定一个未排序的整数数组 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
二、题解
就是需要找到无序的整数数组中最长的连续数字长度,数组元素值能连续就行,不要求下标连续。
方法一
简单的可以先将数组排序,排序之后连续的数字都是相邻的了,所以检查获取最长连续数字的长度即可,但是使用排序就无法达到O(n)的时间复杂度,所以考虑使用其他方法。我们还可以枚举每一个序列,最后保存最长的序列长度就可以了。对于数组的某个元素值x,其下一个连续的整数就应该是x + 1,再下一个就是x + 1 + 1,所以我们可以遍历数组的元素,以每一个元素值为起点,寻找下一个连续的数字,当找不到下一个连续数字就停止,这时的长度就是该元素开始的最长序列长度,最后获取每一个元素开始的最长序列中最大的一个即可。但是这样依旧无法达到O(n)的时间复杂度,需要遍历每一个元素,然后还要遍历数组查询下一个元素,时间复杂度为O(n^2)了,那么我们就需要对查询优化了。为了使查询元素达到O(1)的时间复杂度,我们可以预先存储所有数组元素到哈希表中,这样查询某个元素是否存在的时间复杂度就达到了O(1)。然后就可以愉快的遍历枚举元素了,某些情况下可能存在一些不必要的枚举,例如我们一开始以x为起点枚举了x、x + 1、x + 2、...等,那么之后必定也会有从以x + 1为起点的枚举,那么以x为起点的序列长度必定大于以x + 1为起点的序列,所以对于以x + 1为起点的枚举是没有意义的,因此要选定为起点的元素值x不能存在上一个连续数字即x - 1。最后遍历结束返回最长序列即可。
三、代码
方法一 Java代码
class Solution {
public int longestConsecutive(int[] nums) {
Set<Integer> numSet = new HashSet<Integer>();
for (int num : nums) {
numSet.add(num);
}
int longestConsecutive = 0;
for (Integer num : numSet) {
if (numSet.contains(num - 1)) {
continue;
}
int nextNum = num;
while (numSet.contains(++nextNum)) {
}
longestConsecutive = Math.max(longestConsecutive, nextNum - num);
}
return longestConsecutive;
}
}
时间复杂度:O(n),需要遍历数组每一个元素。
空间复杂度:O(n),需要一个哈希表存储数组每一个元素。