一、题目描述
给定一个未排序的整数数组 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
二、解题思路
要设计一个时间复杂度为O(n)的算法,我们可以使用哈希集合(HashSet)来存储数组中的所有数字。然后,我们可以遍历数组中的每个数字,对于每个数字,我们检查其是否为某个连续序列的最小数字。如果是,我们就更新最长连续序列的长度。
算法步骤如下:
- 将数组中的所有数字添加到哈希集合中。
- 遍历数组中的每个数字,对于每个数字,如果其在哈希集合中且其前一个数字不在哈希集合中,那么这个数字就是某个连续序列的最小数字。
- 对于每个这样的最小数字,我们可以计算以其为起点的连续序列的长度,并更新最长连续序列的长度。
三、具体代码
java
import java.util.HashSet;
import java.util.Set;
public class Solution {
public int longestConsecutive(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
Set<Integer> numSet = new HashSet<>();
for (int num : nums) {
numSet.add(num);
}
int longestStreak = 0;
for (int num : nums) {
if (!numSet.contains(num - 1)) {
int currentNum = num;
int currentStreak = 1;
while (numSet.contains(currentNum + 1)) {
currentNum++;
currentStreak++;
}
longestStreak = Math.max(longestStreak, currentStreak);
}
}
return longestStreak;
}
}
四、时间复杂度和空间复杂度
1. 时间复杂度
- 将数组中的所有数字添加到哈希集合中:这一步的时间复杂度是O(n),因为我们需要遍历数组中的每个数字一次,并将它们添加到哈希集合中。哈希集合的添加操作通常是O(1)的时间复杂度。
- 遍历数组中的每个数字,并计算以它们为起点的连续序列的长度:这一步的时间复杂度也是O(n),因为我们需要遍历数组中的每个数字一次。对于每个数字,我们可能会计算以其为起点的连续序列的长度,这个计算过程在最坏情况下会遍历整个数组,但是由于哈希集合的存在,每个数字只会被计算一次。因此,这一步的整体时间复杂度仍然是O(n)。
- 综上所述,整个算法的时间复杂度是O(n)。
2. 空间复杂度
- 哈希集合:我们需要一个哈希集合来存储数组中的所有数字,因此空间复杂度是O(n),其中n是数组中数字的数量。
- 综上所述,整个算法的空间复杂度是O(n)。
五、总结知识点
-
哈希集合(HashSet):用于存储数组中的所有数字,以便快速判断一个数字是否存在于数组中。哈希集合的特点是添加和查找操作的平均时间复杂度为O(1)。
-
数组遍历:使用for-each循环遍历数组中的每个元素。
-
条件语句:使用if语句来检查数字是否为某个连续序列的最小数字。
-
循环结构:使用while循环来找到以某个数字为起点的最长连续序列。
-
数学运算:使用加减法来生成连续序列中的下一个数字,并使用Math.max函数来更新最长连续序列的长度。
-
函数定义 :定义了一个名为
longestConsecutive
的公共方法,该方法接受一个整数数组作为参数,并返回一个整数作为结果。 -
异常处理:检查输入数组是否为null或长度为0,如果是,则直接返回0,这是一种简单的异常处理方式。
-
变量声明和赋值:声明了多个变量来存储当前的数字、当前的连续序列长度和最长的连续序列长度。
-
算法设计:整个代码的核心是设计了一个时间复杂度为O(n)的算法来找到最长的连续序列,这涉及到对问题的分析和解决方案的设计。
-
代码结构:代码遵循了良好的结构,先处理特殊情况,然后是主要逻辑,最后返回结果。
以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。