最长连续序列
/ / 点击 / 阅读耗时 5 分钟最长连续序列
题目
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
- 示例
1 | 给定一个未排序的整数数组,找出最长连续序列的长度。 |
- 示例:
1 | 输入: [100, 4, 200, 1, 3, 2] |
解题思路
- 围绕 O(n)O(n) 的时间复杂度
- 这些数字用一个 HashSet 保存,实现 O(1)O(1) 时间的查询
- 我们只对 当前数字 - 1 不在哈希表里的数字,作为连续序列的第一个数字去找对应的最长序列,这是因为其他数字一定已经出现在了某个序列里。
代码实现
1 | private static int longestConsecutive() { |
性能分析
一、执行用时分布图表
二、执行消耗内存分布图表
三、复杂度分析
- 时间复杂度:O(n)O(n)
尽管在 for 循环中嵌套了一个 while 循环,时间复杂度看起来像是二次方级别的。但其实它是线性的算法。因为只有当 currentNum 遇到了一个序列的开始, while 循环才会被执行(也就是 currentNum-1 不在数组 nums 里), while 循环在整个运行过程中只会被迭代 nn 次。这意味着尽管看起来时间复杂度为 O(n \cdot n)O(n⋅n) ,实际这个嵌套循环只会运行 O(n + n) = O(n)O(n+n)=O(n) 次。所有的计算都是线性时间的,所以总的时间复杂度是 O(n)O(n) 的。
- 空间复杂度:O(n)O(n)
为了实现 O(1)O(1) 的查询,我们对哈希表分配线性空间,以保存 nums 数组中的 O(n)O(n) 个数字。除此以外,所需空间与暴力解法一致。
总结
- 如果代码中不加如果的if语句也是OK的,但是复杂度就高了很多,大家可以亲测
1 | if (!tempNums.contains(item - 1)) { |