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

文章目录

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

题目

标题和出处

标题:最长连续序列

出处: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 ≤ 10 5 \texttt{0} \le \texttt{nums.length} \le \texttt{10}^\texttt{5} 0nums.length105
  • -10 9 ≤ nums[i] ≤ 10 9 \texttt{-10}^\texttt{9} \le \texttt{nums[i]} \le \texttt{10}^\texttt{9} -109nums[i]109

解法

思路和算法

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

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

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

将数组 nums \textit{nums} nums 中的元素都加入哈希集合之后,遍历哈希集合,对于每个元素 num \textit{num} num,如果 num − 1 \textit{num} - 1 num1 在哈希集合中则跳过 num \textit{num} num,如果 num − 1 \textit{num} - 1 num1 不在哈希集合中则计算从 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} + 1 maxNum+1 在哈希集合中则将 maxNum \textit{maxNum} maxNum 的值加 1 1 1,重复增加 maxNum \textit{maxNum} maxNum 的值,直到 maxNum + 1 \textit{maxNum} + 1 maxNum+1 不在哈希集合中;

  2. num \textit{num} num 开始的最长连续序列的长度是 maxNum − num + 1 \textit{maxNum} - \textit{num} + 1 maxNumnum+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),其中 n n n 是数组 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),其中 n n n 是数组 nums \textit{nums} nums 的长度。需要使用哈希集合存储数组 nums \textit{nums} nums 中的元素,哈希集合中的元素个数不会超过 n n n

你可能感兴趣的:(数据结构和算法,#,哈希表,哈希表)