128. Longest Consecutive Sequence

问题描述:

Given an unsorted array of integers, find the length of the longest consecutive elements sequence.

Your algorithm should run in O(n) complexity.

Example:

Input: [100, 4, 200, 1, 3, 2]
Output: 4
Explanation: The longest consecutive elements sequence is [1, 2, 3, 4]. Therefore its length is 4.

 

解题思路:

讲真这题一开始我没什么思路,然后看到tag里有并查集,我就往并查集的方向想了。

nums中数字n,若n-1出现在nums中,对n 和 n-1执行union操作。

Find方法中用到了路径压缩

最后对每个数字的父节点计算它的子节点的个数,这就是最长的连续数字

这里有一个坑就是数组中的数字可能会出现重复,若直接用数字来标识,那么会出现错误:

如:[0,0,-1]

若对数组中每一个数字进行find并对根节点+1的话,那么最后会得到3。

这里可以用下标来进行标识。

以上只是复习一下并查集。

因为我的并查集只打败了6% ಠ_ಠ

更快的方法:

使用集合存储数组中的数字。

对数组中的每一个数字,首先检查它是否还存在在集合中,若存在,将计数变量cnt设为0并从集合中删除该数字。

此时检查比它小1的数字是否存在,若存在删除它同时计数自增1一,再检查更小的。

对比它大1的数字同理。

 

当遇到这类问题时,我们不一定要考虑如何遍历数组,也可以考虑将其放到一个新的数据结构中。

 

代码:

Union Find:

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        unordered_map<int,int> parents;
        unordered_map<int,int> rec;
        for(int i = 0; i < nums.size(); i++){
            parents[i] = i;
            rec[nums[i]] = i;
        }
        for(auto p : rec){
            if(rec.count(p.first-1)){
                Union(parents, rec[p.first-1] , rec[p.first]);
        }
    }
        return findMax(parents, nums);   
    }
private:
    int find(unordered_map<int,int> &parents, int a){
        if(parents[a] == a)
            return a;
        return parents[a] = find(parents, parents[a]);
    }
    
    void Union(unordered_map<int,int> &parents, int a, int b){
        int rootA = find(parents, a);
        int rootB = find(parents, b);
        if(rootA != rootB)
            parents[rootB] = rootA;
    }
    
    int findMax(unordered_map<int, int> &parents, vector<int> &nums){
        int ret = 0;
        unordered_map<int,int> cnt;
        for(int i = 0; i < nums.size(); i++){
            ret = max(ret, ++cnt[find(parents, i)]);
        }
        return ret;
    }
};

使用集合:

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        unordered_set<int> s(nums.begin(), nums.end());
        int ret = 0;
        for(int i = 0; i < nums.size(); i++){
            if(s.count(nums[i])){
                int cnt = 1;
                int prev = nums[i]-1;
                int next = nums[i]+1;
                s.erase(nums[i]);
                while(s.count(prev)){
                    s.erase(prev);
                    prev--;
                    cnt++;
                }
                while(s.count(next)){
                    s.erase(next);
                    next++;
                    cnt++;
                }
                ret = max(ret, cnt);
            }
        }
        return ret;
        
    }
};

 

posted @ 2018-06-17 05:19  妖域大都督  阅读(122)  评论(0编辑  收藏  举报