2024/6/18 原来今天是618啊,流年似水,岁月如流。最近似乎做题都不太积极,前面的二叉树学的有些模糊,有些抗拒心理,今天总算将二叉树的做过去了。最近又看起了王小波的《黄金时代》,是这本书让我爱上小波,从此我的影子也有了他的痕迹。做道题吧,今天学会docker,论文也要跟上进度了,快点整出来也好放心下一步。
1、题目描述
2、逻辑分析
给一个未排序的整数数组,要找出数字连续的最长序列(不要求序列元素在原数组中连续)。时间复杂度要求O(n)。咋做啊?
我只能想到暴力解法,想不出来了,看看题解。好吧,官网给出的跟我想的差不多。
简单来说就是每个数都判断一次这个数是不是连续序列的开头那个数
怎么判断呢,就是用哈希表查找这个数前面一个数是否存在,即num-1
在序列中是否存在。存在那这个数肯定不是开头,直接跳过。
因此只需要对每个开头的数进行循环,直到这个序列不再连续,因此复杂度是O(n)。
以题解中的序列举例:[100,4,200,1,3,4,2]
去重后的哈希序列为:[100,4,200,1,3,2]
按照上面逻辑进行判断:
- 元素100是开头,因为没有99,且以100开头的序列长度为1
- 元素4不是开头,因为有3存在,过,
- 元素200是开头,因为没有199,且以200开头的序列长度为1
- 元素1是开头,因为没有0,且以1开头的序列长度为4,因为依次累加,2,3,4都存在。
- 元素3不是开头,因为2存在,过,
- 元素2不是开头,因为1存在,过。
完
这是下面的评论给出的解释,比官方的容易懂
3、代码演示
public int longestConsecutive(int[] nums) {
// 创建一个HashSet来存储数组中的数字,以便快速查找
Set<Integer> num_set = new HashSet<Integer>();
// 遍历数组,将数字添加到HashSet中
for(int num : nums){
num_set.add(num);
}
// 初始化最长连续递增子序列的长度为0
int longest_length = 0;
// 遍历HashSet中的每一个数字
for(int num: num_set){
// 如果当前数字的前一个数字不在HashSet中(即当前数字是连续递增子序列的最小值)
if(! num_set.contains(num - 1)){
// 当前检查的数字
int cur_num = num;
// 当前连续递增子序列的长度,初始为1(因为至少包含当前数字)
int cur_length = 1;
// 当当前数字的后一个数字在HashSet中时,继续向后查找
while(num_set.contains(cur_num + 1)){
// 移动到下一个数字
cur_num += 1;
// 连续递增子序列长度加1
cur_length += 1;
}
// 更新最长连续递增子序列的长度
longest_length = Math.max(longest_length, cur_length);
}
}
// 返回最长连续递增子序列的长度
return longest_length;
}
4、复杂度分析
- 时间复杂度:O(n)。
- 空间复杂度:O(n)。哈希表存储数组中所有的数需要 O(n) 的空间。
ok啦,今天这道题还是蛮简单滴啦,我就喜欢做数组相关的,链表、二叉树这些还得多练啊。拜拜!