[路飞]_leetcode_128. 最长连续序列

96 阅读1分钟

给定一个未排序的整数数组 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

解题思路

题目要求实现时间复杂度为 O(n),所以只能对数组遍历一次。
设ind数组,存储nums数组的下标,ind的下标为nums的值,那么我们可以通过并查集,将nums数组的下标连通。

例1中nums数组为[100, 4, 200, 1, 3, 2]

nums: [100, 4, 200, 1, 3, 2]
        0,  1,  2,  3, 4, 5

ind:  [, 3, 5, 4, 1,..., 0,..., 2]
         1  2  3  4     100    200

通过转换我么可以得到nums数组中连续的序列的下标 3,5,4,1。
那么我们将获取最长序列的值转化成获取最长序列的下标的方法,然后通过并查集来获取最长的连续序列的数量。

代码

class UnionSet {
    constructor(n) {
        this.parent = new Array(n + 1).fill(0).map((v, index) => index)
        this.rank = new Array(n + 1).fill(1)
        this.count = n
    }

    getCount() {
        return this.count
    }

    connected(a, b) {
        return  this.find(a) == this.find(b)
    }

    find(x) {
        if (this.parent[x] != x) {
            this.parent[x] =  this.find(this.parent[x])
        }
        return this.parent[x]
    }

    merge(a, b) {
        let ra = this.find(a), rb = this.find(b)
        if (ra == rb) return
        if (this.rank[ra] < this.rank[rb]) {
            this.parent[ra] = rb
            this.rank[rb] += this.rank[ra]
        } else {
            this.parent[rb] = ra
            this.rank[ra] += this.rank[rb]
        }
        this.count--
    }
}
var longestConsecutive = function(nums) {
    if (!nums.length) return 0
    // 存储数组下标
    let ind = new Array()
    let u = new UnionSet(nums.length)
    for ([i, num] of nums.entries()) {
        // 消除重复值
        if (ind[num] != ind[ind.length]) continue;
        // 如果当前数的前一个数有值
        if (ind[num - 1] !== undefined) {
            // 合并的是数组下标
            u.merge(i, ind[num - 1])
        }
        // 如果当前数的后一个数有值
        if (ind[num + 1] !== undefined) {
            u.merge(i, ind[num + 1])
        }
        ind[num] = i // nums下标
    }

    let ans = 0
    for (let i = 0; i < nums.length; i++) {
        // 如果当前下标是树的根节点,且树节点长度大于ans
        if (u.find(i) == i && u.rank[i] > ans) ans = u.rank[i]
    }
    return  ans
};