给定一个未排序的整数数组 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
我们需要找出连续的最长序列,首先我们需要找到的是连续的序列,然后从中找到最长的长度。
找连续数字,就是前后相连的数字,这里我们用到了并查集和map函数。
我们遍历数组,根据题意我们要找的是严格递增的序列,所以相同的数我们只计算一次。
然后将其余的数字都加入到map中,如果该数字的前后数字也存在于map中,将其与该数字用并查集关联到一起。
var longestConsecutive = function (nums) {
let len = nums.length
let u = new UnionSet(len)
let map = new Map()
for (let i = 0; i < len; i++) {
const n = nums[i]
if (map.has(n)) continue
if (map.has(n - 1)) u.merge(i, map.get(n - 1))
if (map.has(n + 1)) u.merge(i, map.get(n + 1))
map.set(n, i)
}
let ans = 0
for (let i = 0; i < len; i++) {
if (u.get(i) == i && u.cnt[i] > ans) ans = u.cnt[i]
}
return ans
};
class UnionSet {
constructor(n) {
this.fa = new Array(n + 1)
this.n = n
this.cnt = new Array(n + 1)
for (let i = 0; i <= n; i++) {
this.fa[i] = i
this.cnt[i] = 1
}
}
get(x) {
return this.fa[x] = (this.fa[x] == x ? x : this.get(this.fa[x]))
}
merge(a, b) {
if (this.get(a) == this.get(b)) return
this.cnt[this.get(b)] += this.cnt[this.get(a)]
this.fa[this.get(a)] = this.get(b)
return
}
}