> 文章列表 > 哈希表题目:最长连续序列

哈希表题目:最长连续序列

哈希表题目:最长连续序列

文章目录

  • 题目
    • 标题和出处
    • 难度
    • 题目描述
      • 要求
      • 示例
      • 数据范围
  • 解法
    • 思路和算法
    • 代码
    • 复杂度分析

题目

标题和出处

标题:最长连续序列

出处:128. 最长连续序列

难度

6 级

题目描述

要求

给定一个未排序的整数数组 nums\\texttt{nums}nums,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

请你设计并实现时间复杂度为 O(n)\\texttt{O(n)}O(n) 的算法解决此问题。

示例

示例 1:

输入:nums=[100,4,200,1,3,2]\\texttt{nums = [100,4,200,1,3,2]}nums = [100,4,200,1,3,2]
输出:4\\texttt{4}4
解释:最长数字连续序列是 [1,2,3,4]\\texttt{[1, 2, 3, 4]}[1, 2, 3, 4]。它的长度为 4\\texttt{4}4

示例 2:

输入:nums=[0,3,7,2,5,8,4,6,0,1]\\texttt{nums = [0,3,7,2,5,8,4,6,0,1]}nums = [0,3,7,2,5,8,4,6,0,1]
输出:9\\texttt{9}9

数据范围

  • 0≤nums.length≤105\\texttt{0} \\le \\texttt{nums.length} \\le \\texttt{10}^\\texttt{5}0nums.length105
  • -109≤nums[i]≤109\\texttt{-10}^\\texttt{9} \\le \\texttt{nums[i]} \\le \\texttt{10}^\\texttt{9}-109nums[i]109

解法

思路和算法

为了寻找最长连续序列,对于数组 nums\\textit{nums}nums 中的元素 num\\textit{num}num,需要找到最大的正整数 kkk,使得从 num\\textit{num}numnum+k−1\\textit{num} + k - 1num+k1 都在数组中,则从 num\\textit{num}num 开始的最长连续序列的长度是 kkk

为了判断一个元素是否在数组中,可以使用哈希集合存储数组中的元素,判断一个元素是否在哈希集合中的时间复杂度是 O(1)O(1)O(1)。假设数组 nums\\textit{nums}nums 的长度是 nnn,如果对数组中的每个元素都进行上述操作,则对于一个元素计算从该元素开始的最长连续序列的长度需要 O(n)O(n)O(n) 的时间,总时间复杂度是 O(n2)O(n^2)O(n2)

为了将时间复杂度降低到 O(n)O(n)O(n),必须进一步优化。对于数组 nums\\textit{nums}nums 中的元素 num\\textit{num}num,如果 num−1\\textit{num} - 1num1 也在数组中,则将 num−1\\textit{num} - 1num1 添加到 num\\textit{num}num 的前面可以使得连续序列的长度加 111,因此从 num−1\\textit{num} - 1num1 开始的最长连续序列的长度一定大于从 num\\textit{num}num 开始的最长连续序列的长度。基于该结论,对于数组 nums\\textit{nums}nums 中的元素 num\\textit{num}num,只有当 num−1\\textit{num} - 1num1 不在数组中时,才需要计算从 num\\textit{num}num 开始的最长连续序列的长度。

将数组 nums\\textit{nums}nums 中的元素都加入哈希集合之后,遍历哈希集合,对于每个元素 num\\textit{num}num,如果 num−1\\textit{num} - 1num1 在哈希集合中则跳过 num\\textit{num}num,如果 num−1\\textit{num} - 1num1 不在哈希集合中则计算从 num\\textit{num}num 开始的最长连续序列的长度,具体做法如下:

  1. maxNum\\textit{maxNum}maxNum 表示从 num\\textit{num}num 开始的最长连续序列的最大元素,初始时 maxNum=num\\textit{maxNum} = \\textit{num}maxNum=num,如果 maxNum+1\\textit{maxNum} + 1maxNum+1 在哈希集合中则将 maxNum\\textit{maxNum}maxNum 的值加 111,重复增加 maxNum\\textit{maxNum}maxNum 的值,直到 maxNum+1\\textit{maxNum} + 1maxNum+1 不在哈希集合中;

  2. num\\textit{num}num 开始的最长连续序列的长度是 maxNum−num+1\\textit{maxNum} - \\textit{num} + 1maxNumnum+1,用该长度更新整个数组的最长连续序列的长度。

遍历结束之后,即可得到整个数组的最长连续序列的长度。

优化后的做法中,由于不可能作为最长连续序列的第一个数的元素会跳过,因此哈希集合中的每个元素只会被遍历一次,时间复杂度是 O(n)O(n)O(n)

代码

class Solution {public int longestConsecutive(int[] nums) {Set<Integer> set = new HashSet<Integer>();for (int num : nums) {set.add(num);}int maxLength = 0;for (int num : set) {if (set.contains(num - 1)) {continue;}int maxNum = num;while (set.contains(maxNum + 1)) {maxNum++;}maxLength = Math.max(maxLength, maxNum - num + 1);}return maxLength;}
}

复杂度分析

  • 时间复杂度:O(n)O(n)O(n),其中 nnn 是数组 nums\\textit{nums}nums 的长度。遍历数组 nums\\textit{nums}nums 并将全部元素加入哈希集合需要 O(n)O(n)O(n) 的时间,遍历哈希集合计算最长连续序列的长度时,由于不可能作为最长连续序列的第一个数的元素会跳过,因此哈希集合中的每个元素只会被遍历一次,时间复杂度是 O(n)O(n)O(n)

  • 空间复杂度:O(n)O(n)O(n),其中 nnn 是数组 nums\\textit{nums}nums 的长度。需要使用哈希集合存储数组 nums\\textit{nums}nums 中的元素,哈希集合中的元素个数不会超过 nnn