秋招 - 算法 - 最长连续序列

63 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第12天,点击查看活动详情 >>

一、题目描述 LeetCode - 128

给定一个未排序的整数数组 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

二、解题思路

题目要求找出数组中最长连续序列,并且不要求元素在原始数组中连续。一种方法是:我们可以考虑先对数组元素去重,再使用快排对数组排序,最后在去重并且排序完成的数组中寻找最长连续序列。还有一种较为简单的做法为:我们在对原始数组去重时可以考虑使用集合结构,其内的元素天然的具有唯一性;在寻找最长连续序列时,可以考虑以 x 为起点的最长连续序列即为 x, x+1, x+2, ..., x+y,其长度为 y+1。如果已知有一个 x, x+1, x+2, ..., x+y 的连续序列,当我们再寻找从 x+1 开始的连续序列时,将会多出一些无用的判断,因为我们已经找到以 x 开始的连续序列,所以相应的可以直接得到以 x+1 开始的连续序列。因此我们在寻找 x 的连续序列时每次在哈希表中检查是否存在 x-1 即能判断是否需要跳过判断了。若 x-1 存在则说明从 x-1 开始的连续序列一定比从 x 开始连续序列长,所以跳过;若不存在,则需要进行判断。

三、代码

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

四、总结

经过集合优化后的算法时间复杂度为O(n),空间复杂度为O(n)。