一、题目描述

给定一个未排序的整数数组,找出最长连续序列的长度。

要求算法的时间复杂度为 O(n)。

示例:

输入: [100, 4, 200, 1, 3, 2]
输出: 4
解释: 最长连续序列是 [1, 2, 3, 4]。它的长度为 4。

二、解题思路 & 代码

2.1 哈希表

class Solution:
    def longestConsecutive(self, nums):
        longest_streak = 0
        num_set = set(nums)

        for num in num_set:
            if num - 1 not in num_set:
                current_num = num
                current_streak = 1

                while current_num + 1 in num_set:
                    current_num += 1
                    current_streak += 1

                longest_streak = max(longest_streak, current_streak)

        return longest_streak

复杂度分析

  1. 时间复杂度:O(n),其中 n 为数组的长度。具体分析已在上面正文中给出。

  2. 空间复杂度:O(n)。哈希表存储数组中所有的数需要 O(n) 的空间。

参考:
LeetCode官方题解

2.2 动态规划

解题思路:
题目要求 O(n) 复杂度。

  1. 用哈希表存储每个端点值对应连续区间的长度
  2. 若数已在哈希表中:跳过不做处理
  3. 若是新数加入:
    1)取出其左右相邻数已有的连续区间长度 leftright
    2)计算当前数的区间长度为:cur_length = left + right + 1
    3)根据 cur_length 更新最大长度 max_length 的值
    4)更新区间两端点的长度值
class Solution(object):
    def longestConsecutive(self, nums):
        hash_dict = dict()
        
        max_length = 0
        for num in nums:
            if num not in hash_dict:
                left = hash_dict.get(num - 1, 0)
                right = hash_dict.get(num + 1, 0)
                
                cur_length = 1 + left + right
                if cur_length > max_length:
                    max_length = cur_length
                
                hash_dict[num] = cur_length
                hash_dict[num - left] = cur_length
                hash_dict[num + right] = cur_length
                
        return max_length

参考:
LeetCode题解

2.3 并查集

class DSU:
    def __init__(self, nums):
        self.pre = {
   num: num for num in nums}
        self.rank = collections.defaultdict(lambda: 1)
        self.cnt = collections.defaultdict(lambda: 1)
    def find(self, x):
        while x != self.pre[x]:
            x = self.pre[x]
        return x
    def merge(self, x, y):
        if y not in self.pre:
            return 1
        root1, root2 = self.find(x), self.find(y)
        if root1 == root2:
            return self.cnt[root1]
        if self.rank[root1] < self.rank[root2]:
            self.pre[root1] = root2
            self.cnt[root2] += self.cnt[root1]
            return self.cnt[root2]
        elif self.rank[root1] > self.rank[root2]:
            self.pre[root2] = root1
            self.cnt[root1] += self.cnt[root2]
            return self.cnt[root1]
        else:
            self.pre[root1] = root2
            self.cnt[root2] += self.cnt[root1]
            self.rank[root2] += 1
            return self.cnt[root2]
class Solution:
    def longestConsecutive(self, nums: List[int]) -> int:
        dsu = DSU(nums)
        res = 0
        for num in nums:
            res = max(res, dsu.merge(num, num + 1))
        return res

参考:
leetCode题解