给定一个未排序的整数数组 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 <= 10^5
-10^9 <= nums[i] <= 10^9
我的题解思路:
定义一个长度len为(数组最大值-数组最小值+1)的布尔型数组,
值都为false。遍历原始整数数组[100,4,200,1,3,2],
例如当前遍历的数为100,则将布尔数组下标
为(len-(max-100)-1)的值改为true。
遍历完原始数组,将对应的布尔数组值改成true。
最后遍历布尔数组,找到最长的连续子序列。
class Solution {
public int longestConsecutive(int[] nums) {
if(nums.length==0)return 0;
int maxValue = 0;
int minValue = 0;
int numsLen = nums.length;// 原始数组的长度
for(int i=0;i<numsLen;i++){//获取到数组中的最大值和最小值
if(nums[i]>maxValue)maxValue = nums[i];
if(nums[i]<minValue)minValue = nums[i];
}
int flagsLen = maxValue-minValue+1;// 布尔数组的长度
boolean[] flags = new boolean[flagsLen];
for(int i=0;i<numsLen;i++){// 修改布尔数组的值
flags[flagsLen-(maxValue-nums[i])-1]=true;
}
int maxLen = 0;//记录最长的连续序列长度
int curLen = 0;//记录当前连续序列长度
for(int i=0;i<flagsLen;i++){
if(flags[i]){//flag值为true表示序列连续,长度+1
curLen++;
if(curLen>maxLen)maxLen=curLen;//当前长度大于之前记录的最长序列长度,更新最长序列长度
}else{// flag为false表示序列不连续,长度归0,重新记录
curLen=0;
}
}
return maxLen;
}
}
报错:
官方题解:
结合官方题解写出代码:
class Solution {
public int longestConsecutive(int[] nums) {
Set<Integer> set = new HashSet<>();
for(int i=0;i<nums.length;i++){// 数组转为list,set
set.add(nums[i]);
}
int maxLen = 0;
int curLen = 0;
for(Integer a:set){// 遍历集合
curLen = 0;//当前长度为0
if(set.contains(a-1))continue;//如何该值的前一个数存在,则跳过,进行下一个值的判断。
for(int i=a;set.contains(i);i++){// 计算连续序列长度。contains的时间复杂度为O(1)
curLen++;
}
if(curLen>maxLen)maxLen=curLen;
}
return maxLen;
}
}
总结:
hash表查看一个值是否存在的时间复杂度为O(1),因此以后需要使用查询效率高的数据结构除了使用数组下标之外,使用hash表和hashset也可以。
避免重复查询,如果存在比这个值小的值,则把查询任务交给值更小的数,该数直接跳过即可。
数组转hashset的方法。循环一个一个加入到set中