美文网首页
128. 最长连续序列【并查集】

128. 最长连续序列【并查集】

作者: 月下蓑衣江湖夜雨 | 来源:发表于2020-08-08 11:03 被阅读0次

    题目

    题目

    思路

    并查集

    代码

    package main
    
    import (
        "bytes"
        "fmt"
    )
    
    // 给定一个未排序的整数数组,找出最长连续序列的长度。
    // 要求算法的时间复杂度为 O(n)。
    //
    // 输入: [100, 4, 200, 1, 3, 2]
    // 输出: 4
    // 解释: 最长连续序列是 [1, 2, 3, 4]。它的长度为 4。
    //
    // 思路:连通性问题,并查集;(一个方向上进行合并)(100和99)(4和3)(200和199)(1和0)(3和2)(2和0)
    //      求集合个数,并查集里填写集合个数
    //
    func longestConsecutive(nums []int) int {
        ufs := NewUnionFindSet(nums)
        //fmt.Printf("before ufs is %v\n\n", ufs)
    
        // [0, 0, -1],重复的只处理1遍!
        processedMap := make(map[int]bool)
        for _, num := range nums {
            if _, ok := processedMap[num]; !ok {
                ufs.Union(num, num-1)
                processedMap[num] = true
            }
        }
        //fmt.Printf("after ufs is %v\n\n", ufs)
    
        res := 0
        for k, v := range ufs.Set {
            if k == v[0] && v[1] > res {
                res = v[1]
            }
        }
    
        return res
    }
    
    // 构造一个ufs
    type UnionFindSet struct {
        Set map[int]*[2]int   // key是元素,value[0]是父节点,value[1]是集合元素个数
    }
    
    func NewUnionFindSet(nums []int) *UnionFindSet {
        ufs := &UnionFindSet{Set: make(map[int]*[2]int)}
        for _, v := range nums {
            // [0, 0, -1],重复的不要
            if _, ok := ufs.Set[v]; !ok {
                ufs.Set[v] = &[2]int{v, 1}
            }
        }
        return ufs
    }
    
    // find,查找元素i的主人,并在此过程中,将自己主人的值为最顶层的主人
    func(ufs *UnionFindSet) FindRoot(x int) int {
        if ufs.Set[x][0] != x { // 自己不是顶层root
            // 为什么非指针的话,赋不了值
            ufs.Set[x][0] = ufs.FindRoot(ufs.Set[x][0]) // 找到自己父节点的root,置到自己的父节点(还不是root)
            // 1、元素个数,确保了集合总数都在根节点上
            ufs.Set[ufs.Set[x][0]][0] += ufs.Set[x][1]
            ufs.Set[x][1] = 0
        }
    
        return ufs.Set[x][0] // 返回自己的父节点(已经为root了)
    }
    
    // union: 合并元素x和元素y
    // 合并后,Value存储的不一定是root,最后一次的时候,全部FindRoot一下?
    func(ufs *UnionFindSet) Union(x, y int) {
        // 可能不存在
        _, okx :=ufs.Set[x]
        _, oky :=ufs.Set[y]
    
        if !okx || !oky {
            return
        }
    
        rootX := ufs.FindRoot(x)
        rootY := ufs.FindRoot(y)
    
        if rootX > rootY {
            rootX, rootY = rootY, rootX
        }
    
        // rootX < rootY
        ufs.Set[rootY][0] = rootX
        // 2、元素个数,确保了集合总数都在根节点上
        ufs.Set[rootX][1] += ufs.Set[rootY][1]
        ufs.Set[rootY][1] = 0
    }
    
    func(ufs *UnionFindSet) String() string {
        var strBuf bytes.Buffer
        strBuf.WriteString("UFS:<\n")
        for k,v := range ufs.Set {
            strBuf.WriteString(fmt.Sprintf("%v:[根节点:%v, 集合个数:%v]\n", k, v[0], v[1]))
        }
        strBuf.WriteString(">\n")
        return strBuf.String()
    }
    

    结果

    结果

    相关文章

      网友评论

          本文标题:128. 最长连续序列【并查集】

          本文链接:https://www.haomeiwen.com/subject/rzzcdktx.html