题目描述:
给定一个未排序的整数数组 nums
,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n)
的算法解决此问题。
示例:
输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。
解题思路:
(1)结合题目的要求我们可以提取到是快速查找+去重!立马联想到是用HashSet
为什么去重?因为如果给出的nums是1,2,2,3,4;我们最终也是要1,2,3,4,所以需要去重哦~~~~
(2)然后思考怎么实现?观察需求,需要类似1,2,3,4这样的连续的序列,也就是说要越来越大的连续序列,提取关键字:越来越大,且是一个比一个大1!
那可以得出,当我们找到1之后,我们需要判断2在里面吗?3在里面吗?4在里面吗?
即:num+1在里面吗?num+2在里面吗?num+3在里面吗?.........直到断掉!
(3)好,第二个要思考我们怎么找到这个1?也就是说我们怎么找到这个起始的数字?
可以发现,1 是连续序列里面开头的,即最小的!只要我们确定1最小即可!
推出=>有没有比1还小的在里面?即1-1是否存在?存在的话那么1就不是最小的了,不存在那我1就是最小的,我们就可以继续上面的num+1、num+2的判断了~~~
总结步骤:
把所有数字扔进哈希集合(去重+快速查找)。
遍历数组,找序列开头:对于每个数
num
,检查num-1
是否在集合中:
如果
num-1
不存在,说明num
可能是某个序列的开头。如果
num-1
存在,跳过(因为它不是开头)直接不检查了。扩展序列:如果是开头,就不断检查
num+1
、num+2
... 是否在集合中,直到断掉。更新最长长度。
JAVA代码实现:
import java.util.HashSet;
import java.util.Set;
public class LongestConsecutiveSequence {
public int longestConsecutive(int[] nums) {
Set<Integer> numSet = new HashSet<>();
for (int num : nums) {
numSet.add(num); // 所有数字存入HashSet
}
int maxLength = 0;
for (int num : nums) {
// 检查是否是序列开头(没有比它更小的数)
if (!numSet.contains(num - 1)) {
int currentNum = num;
int currentLength = 1;
// 向后扩展序列
while (numSet.contains(currentNum + 1)) {
currentNum++;
currentLength++;
}
// 每次找到一个新序列时,需判断它是否比之前记录的更长
maxLength = Math.max(maxLength, currentLength);
}
}
return maxLength;
}
}
解析查找过程:
第一个检查100: 100-1=99在不在里面?99不在!那么100可能就是开头的,继续100+1在不在?,不在!断了....
第二个检查4: 4-1=3在不在? 3在哦!!那直接不检查了
第三个检查200: 200-1=199在不在? 不在!继续200+1=201在不在?不在!断了....
第三个检查1: 1-1=0在不在?不在,继续1+1=2在不在?2存在!,1+2=3在不在?,3也存在,1+3=4在不在?4也存在!1=4=5在不在?5不在!!断了,最长就是1234了
第四个检查3: (不想写了T-T)
第五个检查2:(不想写了T-T)
为什么是 O(n) 时间复杂度?
虽然代码中有嵌套循环(for
+ while
),但实际每个数字最多被访问 两次:
-
第一次:在
for
循环中遍历到。 -
第二次:在
while
循环中作为某个序列的后续数字被检查。
既然这里用到了HashSet,那就补充一下这个知识点吧~~
HashSet
HashSet 是 Java 集合框架中的一个类,它实现了 Set 接口,基于哈希表(Hash Table)的数据结构。
HashSet特点:
- 基于哈希表实现
- HashSet 内部使用哈希表来存储元素,哈希表是一种高效的数据结构,支持快速的插入、删除和查询操作
- 不允许重复元素/对象
- HashSet 中的元素是唯一的,如果尝试添加重复元素,添加操作会被忽略。
- 元素的唯一性是通过 equals() 和 hashCode() 方法来判断的
- 无序性
- HashSet 不保证元素的顺序,元素的存储顺序可能与插入顺序不同。取决于 hash 后,再确定索引的结果
- 允许 null 元素
- HashSet 允许存储 null 值,但只能存储一个 null
- 非线程安全
- HashSet 不是线程安全的