【LC100】No128. 最长连续序列
题目描述
给定一个未排序的整数数组 nums
,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n)
的算法解决此问题。
提示:
0 <= nums.length <= 105
-109 <= nums[i] <= 109
示例
示例 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
示例 3:
输入:nums = [1,0,1,2]
输出:3
链接
思路
沾沾自喜地做完之后,发现题目要求用 O(n) 的复杂度解决问题,自闭了。
看到题目中“只需要返回长度,且不要求序列元素在原数组中连续”,我们可以非常容易地想到排序后再处理。但题目要求 O(n) 时间复杂度,排序会变成 O(nlogn),所以不能用排序。
设数组下标为 i,我们需要分别找到以 nums[i] 开头的最长连续序列,最后返回最大的长度。
也即,根据 nums[i],依次寻找 nums[i]+1、nums[i]+2...是否存在在数组中。
看示例可知,相等元素不计入长度计算,所以还需要去重;同时还需要快速查找某元素是否存在于数组中。
综合上述两点,可以想到将数组转化为 set 。
本题解法中有个非常巧妙的思路:剪枝,省去操作一些“已经从开头就知道这个不是最优解”的情况。
对于 nums[i],如果 nums[i]-1 在 set 中,那么没必要继续找 nums[i] 开头的序列,以 nums[i]-1 开头的序列一定比这个长。
解法:哈希set+剪枝
代码
class Solution {
public int longestConsecutive(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
// 转化为set:去重+方便拿取
Set<Integer> numSet = new HashSet<>();
for (int num : nums) {
numSet.add(num);
}
int maxRes = 1;
for (int num : numSet) {
// 剪枝
if (numSet.contains(num - 1)) {
continue;
}
int maxTemp = 1;
int numTemp = num;
while (numSet.contains(++numTemp)){
maxTemp++;
}
maxRes = Math.max(maxRes, maxTemp);
}
return maxRes;
}
}
时间复杂度:O(n)
空间复杂度:O(n)
【LC100】No128. 最长连续序列
https://tiamo495.com//archives/lc100-no128.-zui-chang-lian-xu-xu-lie