题解一
func longestConsecutive(nums []int) int {
if len(nums) == 0 {
return 0
}
var uf = NewUnionFind(nums)
for _, n := range nums {
// 合并相邻两个集合
uf.union(n, n+1)
}
var m = 1
for _, n := range nums {
f := uf.find(n)
m = max(m, f-n+1)
}
return m
}
// UnionFind 使用并查集的方法解答
type UnionFind struct {
parent map[int]int
}
func NewUnionFind(nums []int) *UnionFind {
parent := make(map[int]int)
for _, n := range nums {
parent[n] = n
}
return &UnionFind{
parent: parent,
}
}
func (u *UnionFind) union(n, m int) {
root_n := u.find(n)
root_m := u.find(m)
if root_m == math.MaxInt || root_n == math.MaxInt {
return
}
if root_n == root_m {
// 两个集合的父节点是一样的,不需要合并
return
}
if root_n > root_m {
u.parent[root_m] = root_n
} else {
u.parent[root_n] = root_m
}
}
func (u *UnionFind) find(n int) int {
if _, ok := u.parent[n]; !ok {
return math.MaxInt
}
if u.parent[n] != n {
u.parent[n] = u.find(u.parent[n])
}
return u.parent[n]
}
题解二
func longestConsecutive1(nums []int) int {
numMap := map[int]bool{}
res := 0
// 生成数组的 hash 结果
for _, num := range nums {
numMap[num] = true
}
for num := range numMap {
// 先找到第一个连续序列的最小值
if numMap[num-1] {
continue
}
// 然后从最小值开始记录该序列的长度
cur := num
for numMap[cur+1] {
cur++
}
// 比较并记录最大值
res = max(res, cur-num+1)
}
return res
}
要点
-
题解一种使用 Union-Find 的思路解答,不断合并相邻的集合。不过这种方法不太直观。
-
题解二的思路比较直观,容易理解:假设 nums 数组中存在 2 个序列,在遍历列表的时候,当 n-1 不存在的时候,意味着 n 是其所在序列中的最小值,然后不断判断 n+1 是否存在该序列中同时更新序列的长度;