题目链接:最长连续序列
题目描述:给定一个未排序的整数数组,找出最长连续序列的长度。
要求算法的时间复杂度为 O(n)。
示例:
输入: [100, 4, 200, 1, 3, 2]
输出: 4
解释: 最长连续序列是 [1, 2, 3, 4]。它的长度为 4。
题目分析:关键点要求时间复杂度为O(n),那么排序啥的自然就不能用。先求出连续序列,然后找个最长的。这里主要是借助哈希去重表,如何达到O(n)的复杂度呢?在暴力枚举的过程中,我们在对每个数寻找连续序列的过程中进行了很多重复的判断,使用set可以把这些重复去掉,大大的简化了复杂度。对于每个连续序列,我们从第一个数开始,依次往后,保证了每个序列的数只被遍历一次,最后加起来是n。可以理解为数组一共有a个序列组成,每个序列只遍历了一次。
代码:
class Solution {
public int longestConsecutive(int[] nums) {
if(nums.length == 0||nums.length==1) return nums.length;
HashSet<Integer> st = new HashSet<>();
for(int num:nums){
st.add(num);
}
int res = 0;
for(int num:st){
if(!st.contains(num-1)){//保证num是某个序列的开始
int cur = num;
int curLen = 1;
while(st.contains(cur+1)){//找这个序列的连续长度
cur+=1;
curLen+=1;
}
res = Math.max(res,curLen);//更新最大值
}
}
return res;
}
}
一开始我是使用的痛排序的算法,因为桶排序的时间复杂度可以达到O(n),无非是以时间换空间的思想,但是桶排序比较头疼的点就是存在溢出和边界处理,是过不了所有用例的,这里就当提供一种思路吧,后续再完善。。
class Solution {
public int solve(int maxNum,int[] bool){
maxNum = Math.abs(maxNum);
int res = 1,cur = 1;
for(int i = 0;i < maxNum;i++){
if(bool[i]==1&&bool[i+1]==1){
cur += 1;
res = Math.max(res,cur);
}else{
cur = 1;
}
}
return res;
}
public int longestConsecutive(int[] nums) {
if(nums.length == 0||nums.length==1) return nums.length;
int n = nums.length,res = 1;
int maxNum = 0,minNum = 0;
for(int i = 0;i < n;i++){
maxNum = Math.max(maxNum,nums[i]);
minNum = Math.min(minNum,nums[i]);
}
int[] bool = new int[maxNum+1];
int[] bool1 = new int[Math.abs(minNum)+1];
for(int i = 0;i < n;i++){
if(nums[i]>=0) bool[nums[i]]=1;
else bool1[Math.abs(nums[i])]=1;
}
int positive = solve(maxNum,bool);
int negtive = solve(minNum,bool1);
// System.out.println(positive+" "+negtive);
if(bool[0]==1&&bool[1]==1&&bool1[1]==1)
return positive+negtive;
else return Math.max(positive,negtive);
}
}
这里我把正负数分开处理,其实可以合并到一个数组里面,不想写了😂😂😂