【leetcode 】128. 最长连续序列 ,并查集 + hash

题目

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

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

示例:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-consecutive-sequence

思路

就是将nums[i]与数组中存在的nums[i-1],nums[i+1]合并成一个集合,最后返回最大的那个集合就好。

细节实现

为了将每一个数字都存储下来,需要一个映射,通过hashMap将nums[i] 映射成 i,

这样就将很大的数字的合并转化成范围小的数组下标的合并。

代码

class Solution {
public:
    class unionSet{
    private:
        int ans;
        vector<int> fa;
        vector<int> size;
        unordered_map<int, int> hashMap;
        void __merge(int a, int b) {
            int aa = get(a), bb = get(b);
            if (aa == bb) return;
            fa[aa] = bb;
            size[bb] += size[aa];
            ans = max(ans, size[bb]);
        }
    public:
        unionSet(int n = 0): ans(1), fa(n), size(n, 1) {
            for(int i = 0; i < n; i++) fa[i] = i;
        }
        int set(int i, int ind) {
            if (hashMap.find(i) != hashMap.end()) return 1;
            hashMap[i] = ind;
            return 0;
        }
        int get(int x) {
            return fa[x] = (fa[x] == x ? x : get(fa[x]));
        }
        int maxSize() {
            return ans;
        }
        void merge(int a, int b) {
            auto i = hashMap.find(b);
            if (i == hashMap.end()) return; 
            __merge(a, i->second);
        }
    };
    int longestConsecutive(vector<int>& nums) {
        if (nums.size() == 0) return 0;
        unionSet u(nums.size());
        for (int i = 0; i < nums.size(); i++) {
            if (u.set(nums[i], i)) continue;
            u.merge(i, nums[i] - 1);
            u.merge(i, nums[i] + 1);
        }
        return u.maxSize();
    }
};

执行用时 :16 ms, 在所有 C++ 提交中击败了83.40%的用户

总结

  1. 用hashMap来做一个很大数的一个离散化的映射
  2. 其实这相当于是一个分组问题,当i-1 , i , i + 1 是关系,连续的序列就是一个组。

你可能感兴趣的:(c++,LeetCode,数据结构)