欢迎使用CSDN-markdown编辑器

Leetcode128 “Longest Consecutive Sequence”

求一个数组的最长连续子序列

题目描述:Given an unsorted array of integers, find the length of the longest consecutive elements sequence.
For example,
Given [100, 4, 200, 1, 3, 2],
The longest consecutive elements sequence is [1, 2, 3, 4]. Return its length: 4.
Your algorithm should run in O(n) complexity.

思路:

第一种方法 利用并查集的思想 使用Weighted-Quick-Union算法(路径压缩,合并优化) 进行实现

如果nums数组中的数不在map中 那么就把它放入
然后判断它的-1 和 +1的数 在不在map之中 如果在 就进行merge操作 更新size数组的值
Weighted-Quick-Union算法的思想是:根据两个集合的秩进行合并,所以哪个集合的元素数量多,merge的时候这个集合就成为父节点。

代码如下:

class Solution {
public:
    vector<int> father;
    vector<int> size;
public:
    int longestConsecutive(vector<int>& nums) {
        int n = nums.size();
        if(n < 2) {
            return n;
        }
        size = vector<int>(n, 1);
        for(int i = 0; i < n; ++i) {
            father.push_back(i);
        }
        unordered_map<int, int> m_map;
        for(int i = 0; i < n; ++i) {
            if(m_map.find(nums[i]) != m_map.end()) continue;
            m_map[nums[i]] = i;
            if(m_map.find(nums[i] - 1) != m_map.end()) {
                unionset(i, m_map[nums[i] - 1]);
            }
            if(m_map.find(nums[i] + 1) != m_map.end()) {
                unionset(i, m_map[nums[i] + 1]);
            }        
        }  
        int ans = *max_element(size.begin(), size.end());
        return ans;
    }

    int find(int idx) {//递归查找父节点 进行路径压缩
        if(father[idx] == idx) {
            return idx;
        }
        int father_idx = find(father[idx]);
        father[idx] = father_idx;
        return father_idx;
    }

    void unionset(int idx1, int idx2) {//进行merge操作
        int p = find(idx1);
        int q = find(idx2);
        if(size[p] > size[q]) {
            father[q] = p;
            size[p] += size[q];
        } else {
            father[p] = q;
            size[q] += size[p];
        }
        return ;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值