哈希:最长连续序列

题目描述:无序的整型数组,求连续最长序列。

输入:nums = [100,4,200,1,3,2]

输出:4 (因为:最长数字连续序列是 [1, 2, 3, 4],长度为 4。)

说明:连续指的是数字的连续,算法要求时间复杂度为O(n)。


求解思路:遍历数组,依次往下找。在找的过程中,因为求最长,所以找的时候需要确定当前数是序列最小,否则没必要。用Set容器存储所有数作为辅助,方便确定我们找的连续序列中的数是否存在。(因为求解的最长序列,不要求在数组连续,所以想到用set去重也不会影响结果。)

java 复制代码
class Solution {
    public int longestConsecutive(int[] nums) {
        int longest = 0;

        // 把所有数存在set中,方便查找
        HashSet<Integer> set = new HashSet<>();
        for (int num : nums) {
            set.add(num);
        }

        // 遍历,寻找最长连续序列
        for (int i = 0; i < nums.length; i++) {
            int curNum = nums[i];

            //判断前驱存不存在很重要!确保序列是从最小的curNum开始
            if (!set.contains(curNum - 1)) {
                // curNum是序列的开头,len为1
                int len = 1;
                // 寻找curNum的下个数。前置++,++curNum和curNum+1效果一样,但是++或者--一般用在遍历,curNum+1更方便理解
                while (set.contains(curNum + 1)) {
                    len += 1;
                    curNum += 1;
                }
                longest = Math.max(longest, len);
            }
        }
        return longest;
    }
}

以上代码,会报超时。

再次优化,遍历set代替遍历nums。

java 复制代码
class Solution {
    public int longestConsecutive(int[] nums) {
        int longest = 0;

        // 把所有数存在set中,方便查找
        HashSet<Integer> set = new HashSet<>();
        for (int num : nums) {
            set.add(num);
        }

        // 遍历set,因为set中比原数组数少,不存在重复的
        for (Integer num : set) {
            // 之所以这里需要使用curNum把num记录下来,因为num是for循环进行的条件。和for(i...len)不同
            int curNum = num;
            if (!set.contains(curNum - 1)) {
                int len = 1;
                while (set.contains(curNum + 1)) {
                    len += 1;
                    curNum += 1;
                }
                longest = Math.max(longest, len);
            }
        }
        return longest;
    }
}

总结:判断cur-1是核心,确保序列开头最小。遍历set是其二,省去重复的计算。

联系地址:128. 最长连续序列 - 力扣(LeetCode)