最长连续序列

76 阅读1分钟

题目链接:leetcode.cn/problems/lo…

题解一

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 是否存在该序列中同时更新序列的长度;