128-Longest Consecutive Sequence

Description:
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.

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

例子:
输入为[100, 4, 200, 1, 3, 2]
最长连续序列为[1, 2, 3 , 4],因此返回4

解法1:

/*
对数组排序,迭代数组,对数组划分连续区间,找出最长的连续区间,划分规则如下:
start  = nums[0], maxCount为最长连续区间的长度,segCount为当前区间的长度
若nums[i] = start + 1,则当前区间长度+1,将start置为nums[i]
若nums[i] > start + 1,maxCount = Math.max(maxCount, segCount),将start置为nums[i], segCount = 1(开始新区间)
若nums[i] = start(由于已经排好序,只剩下这种可能),则忽略

*/
class Solution {
    public int longestConsecutive(int[] nums) {
        if(nums == null || nums.length == 0)    return 0;

        int maxCount = 1,segCount = 1;
        Arrays.sort(nums);
        int start = nums[0];
        for(int i = 1;i < nums.length;i++){
            if(nums[i] == start + 1){
                segCount++;
                start = nums[i];
            }else if(nums[i] > start + 1){
                start = nums[i];
                maxCount = Math.max(segCount, maxCount);
                segCount = 1;
            }
        }

        return Math.max(segCount, maxCount);
    }
}

解法2(并查集):

/*
并查集的关键是两个方法,find(),用于找出根节点,Union()用于合并
有两点需要注意:
1.map相当于'过滤'了重复元素,只取最右边的那个下标
2.sz数组存储的即为区间长度
*/
class Solution {
    public int longestConsecutive(int[] nums) {
        int n = nums.length;
        UnionFind uf = new UnionFind(n);

        Map<Integer, Integer> map = new HashMap<>(); 
        for (int i = 0; i < n; i++) map.put(nums[i], i);

        for (int num : nums)
            if (map.containsKey(num+1))
                uf.union(map.get(num), map.get(num+1));

        return uf.getMaxSize();
    }

    private class UnionFind {
        private int[] id;
        private int[] sz;
        private int maxSize;

        public UnionFind(int n) {
            id = new int[n];
            sz = new int[n];
            for (int i = 0; i < n; i++) {
                id[i] = i;
                sz[i] = 1;
            }
            maxSize = n > 0 ? 1 : 0;
        }

        public int findRoot(int i) {
            if (i == id[i])  return i;
            id[i] = findRoot(id[i]);
            return id[i];
        }

        public void union(int p, int q) {
            int rootP = findRoot(p);
            int rootQ = findRoot(q);

            if (rootP == rootQ)  return;
            if (sz[rootP] < sz[rootQ]) {
                id[rootP] = rootQ;
                sz[rootQ] += sz[rootP];
                maxSize = Math.max(maxSize, sz[rootQ]);
            } else {
                id[rootQ] = rootP;
                sz[rootP] += sz[rootQ];
                maxSize = Math.max(maxSize, sz[rootP]);
            }
        }

        public int getMaxSize() {
            return this.maxSize;
        }
    }
}

虽然第一种解法最快(beats 100%),也是有必要掌握并查集算法的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值