Leetcode-128. 最长连续序列

in with 0 comment

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

方法一:哈希表

class Solution {
    public int longestConsecutive(int[] nums) {
        Set<Integer> num_set = new HashSet<Integer>();
        for (int num : nums) {
            num_set.add(num);
        }

        int longestStreak = 0;

        for (int num : num_set) {
            if (!num_set.contains(num - 1)) {
                int currentNum = num;
                int currentStreak = 1;

                while (num_set.contains(currentNum + 1)) {
                    currentNum += 1;
                    currentStreak += 1;
                }

                longestStreak = Math.max(longestStreak, currentStreak);
            }
        }

        return longestStreak;
    }
}

复杂度分析

方法二:哈希表 + 动态规划

拿当前数字去找与其左右相连的数字集合看看能否组成一个更大的集合,并更新两端的最长值,过程中遇到哈希表中已存在的值就跳过,并且维护一个最大值用于返回

import java.util.HashMap;
import java.util.Map;

class Solution {
    public int longestConsecutive(int[] nums) {
        Map<Integer, Integer> map = new HashMap<>();
        int max = 0;
        for (int i = 0; i < nums.length; i++) {
            if (map.containsKey(nums[i])) continue;
            int left = map.getOrDefault(nums[i] - 1, 0);
            int right = map.getOrDefault(nums[i] + 1, 0);
            int len = left + right + 1;
            max = Math.max(max, len);
            map.put(nums[i], len);
            map.put(nums[i] - left, len);
            map.put(nums[i] + right, len);
        }
        return max;
    }
}

复杂度分析

方法三:并查集

将相邻的数字合并起来,然后再遍历一遍记录最大值即可

import java.util.HashMap;
import java.util.Map;

class Solution {
    class UnionFind{
        Map<Integer, Integer> parents;

        public UnionFind(int[] arr) {
            parents = new HashMap<>();
            for (int i : arr) {
                parents.put(i, i);
            }
        }

        public Integer find(int x) {
            if (!parents.containsKey(x)) return null;
            int t = parents.get(x);
            if(x != t) parents.put(x, find(t));
            return parents.get(x);
        }

        public boolean union(int x, int y) {
            Integer rootX = find(x), rootY = find(y);
            if (rootX == null || rootY == null) return false;
            if(rootX.equals(rootY)) return false;
            parents.put(rootX, rootY);
            return true;
        }
    }
    public int longestConsecutive(int[] nums) {
        if (nums.length == 0) return 0;
        UnionFind u = new UnionFind(nums);
        for (int num : nums) {
            u.union(num, num + 1);
        }
        int max = 1;
        for (int num : nums) {
            max = Math.max(max,u.find(num) - num + 1);
        }
        return max;
    }
}

复杂度分析