目录
1. 题目
给定一个未排序的整数数组 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
2. 分析
首先如果复杂度为O(n2)的话,这题就很好解答了,可以先进行排序,然后在一个循环里面 遍历找到最长连续序列。或者可以使用两个循环来解决。但是题目要求时间复杂度为O(n),所以排序这块先不考虑。那么考虑两个循环的解决方法,怎么将两个循环变成一个循环?这就需要在循环上增加判断条件。
可以这样想,从第一个数开始,如果有比它小1的数,跳过,没有比它小1的数,进入循环,进入循环后判断是否有比他大1的数,如果有,进入第二层循环,然后当前数值+1,当前最长序列值+1,继续在这个循环里判断是否有连续数值。不符合条件的话跳出循环,继续往下走。
我们来分析,虽然用到了两个循环,外层循环复杂度为O(n),但是只有当一个数是连续序列的最小值时才会进入内层循环,所以每个数只会进入内循环一次,综合来说,时间复杂度为O(n)。
3. 题解
题目给的是数组,首先将数组转换为HashSet,进行去重,并且容易找出Set中是否包含某一个值。话不多说,直接上代码
class Solution {
public int longestConsecutive(int[] nums) {
if(nums.length == 0) {
return 0;
}
if(nums.length == 1) {
return 1;
}
Set<Integer> num_set = new HashSet<Integer>();
for (int num : nums) {
num_set.add(num);
}
int longestStreak = 0;
for (int num : num_set) {
if (!num_set.contains(num - 1)) {
int currentNum = num;
int currentStreak = 1;
while (num_set.contains(currentNum + 1)) {
currentNum += 1;
currentStreak += 1;
}
longestStreak = Math.max(longestStreak, currentStreak);
}
}
return longestStreak;
}
}
4. 总结
这个双重带条件循环,时间复杂度为O(n),可以用来解决最长连续序列,最长连续序列和等问题。