zoukankan      html  css  js  c++  java
  • leetcode刷题笔记310题 最小高度树

    leetcode刷题笔记310题 最小高度树

    源地址:310. 最小高度树

    问题描述:

    树是一个无向图,其中任何两个顶点只通过一条路径连接。 换句话说,一个任何没有简单环路的连通图都是一棵树。

    给你一棵包含 n 个节点的数,标记为 0 到 n - 1 。给定数字 n 和一个有 n - 1 条无向边的 edges 列表(每一个边都是一对标签),其中 edges[i] = [ai, bi] 表示树中节点 ai 和 bi 之间存在一条无向边。

    可选择树中任何一个节点作为根。当选择节点 x 作为根节点时,设结果树的高度为 h 。在所有可能的树中,具有最小高度的树(即,min(h))被称为 最小高度树 。

    请你找到所有的 最小高度树 并按 任意顺序 返回它们的根节点标签列表。

    树的 高度 是指根节点和叶子节点之间最长向下路径上边的数量。

    示例 1:

    输入:n = 4, edges = [[1,0],[1,2],[1,3]]
    输出:[1]
    解释:如图所示,当根是标签为 1 的节点时,树的高度是 1 ,这是唯一的最小高度树。
    示例 2:

    输入:n = 6, edges = [[3,0],[3,1],[3,2],[3,4],[5,4]]
    输出:[3,4]
    示例 3:

    输入:n = 1, edges = []
    输出:[0]
    示例 4:

    输入:n = 2, edges = [[0,1]]
    输出:[0,1]

    提示:

    1 <= n <= 2 * 104
    edges.length == n - 1
    0 <= ai, bi < n
    ai != bi
    所有 (ai, bi) 互不相同
    给定的输入 保证 是一棵树,并且 不会有重复的边

    //使用树状DP处理,通过一次遍历获取所有节点的up与d数组数据
    //up数组表示向上方向最大长度, d1数组表示向下方向最大长度
    //d2数组记录不严谨的次大长度,用于x为u的向下最大长度的子节点时,防止出现回路情况
    //通过维护三个数组,可得出节点u的向上及向下的最大长度,即树高情况
    //通过遍历所有结果,获取最小树高
    import scala.collection.mutable
    import util.control.Breaks._
    object Solution {
        def findMinHeightTrees(n: Int, edges: Array[Array[Int]]): List[Int] = {
            val graph = mutable.Map[Int, mutable.Set[Int]]()
            for (i <- 0 to n-1) graph.put(i, mutable.Set[Int]())
            for (e <- edges) {
                graph(e(0)).add(e(1))
                graph(e(1)).add(e(0))
            }
    
            val d1 = Array.fill(n+1)(0)
            val d2 = Array.fill(n+1)(0)
            val p1 = Array.fill(n+1)(0)
            val up = Array.fill(n+1)(0)
    
            def dfs1(u: Int, father: Int): Unit = {
                for (x <- graph(u)){
                    breakable{
                        if (x == father) break()
                        dfs1(x, u)
                        var d = d1(x)+1
                        if (d >= d1(u)) {
                            d2(u) = d1(u)
                            d1(u) = d
                            p1(u) = x
                        } else if (d > d2(u)){
                            d2(u) = d
                        }
                    }
                }
            }
    
            def dfs2(u: Int, father: Int): Unit = {
                for (x <- graph(u)) {
                    breakable{
                        if (x == father) break()
                        if (p1(u) == x) {
                            up(x) = math.max(up(u), d2(u))+1
                        } else {
                            up(x) = math.max(up(u), d1(u))+1
                        }
                        dfs2(x, u)
                    }
                }
            }
    
            dfs1(0, -1)
            
            dfs2(0, -1)
            
            var mind = n + 1
            for (i <- 0 to n-1){
                mind = math.min(mind, math.max(up(i), d1(i)))
            }
    
            val res = mutable.ListBuffer[Int]()
            for (i <- 0 to n-1){
                if (math.max(up(i), d1(i)) == mind) res.append(i)
            }
            return res.toList
    
            /*
            def dfs1(u: Int, father: Int): Unit = {
                for (x <- graph(u)){
                    breakable{
                        if (x == father) break()
                        dfs1(x, u)
                        var d = d1(x)+1
                        if (d >= d1(u)) {
                            d2(u) = d1(u)
                            d1(u) = d
                            p1(u) = x
                        } else if (d > d2(u)){
                            d2(u) = d
                        }
                    }
                }
            }
    
            def dfs2(u: Int, father: Int): Unit = {
                for (x <- graph(u)) {
                    breakable{
                        if (x == father) break()
                        if (p1(u) == x) {
                            up(x) = math.max(up(u), d2(u))+1
                        } else {
                            up(x) = math.max(up(u), d1(u))+1
                        }
                        dfs2(x, u)
                    }
                }
            }
            */
        return res.toList
        }
    }
    
    var graph map[int][]int
    var d1, d2, p1, up []int
    
    func findMinHeightTrees(n int, edges [][]int) []int {
        graph = make(map[int][]int, n)
        for _, e := range edges {
            u, v := e[0], e[1]
            graph[u] = append(graph[u], v)
            graph[v] = append(graph[v], u)
        }
    
        d1, d2, p1, up = make([]int, n+1), make([]int, n+1), make([]int, n+1), make([]int, n+1)
        dfs1(0, -1)
        dfs2(0, -1)
    
        mind := n + 1
        for i := 0; i < n; i++ {
            mind = min(mind, max(up[i], d1[i]))
        }
        res := make([]int, 0)
        for i := 0; i < n; i++ {
            if max(up[i], d1[i]) == mind {
                res = append(res, i)
            }
        }
        return res    
    }
    
    func dfs1(u int, father int) {
        for _, x := range graph[u] {
            if x == father {continue}
            dfs1(x, u)
            d := d1[x]+1
            if d >= d1[u] {
                d1[u], d2[u] = d, d1[u]
                p1[u] = x
            } else if d > d2[u]{
                d2[u] = d
            }
        }
    }
    
    func dfs2(u int, father int) {
        for _, x := range graph[u] {
            if x == father {continue}
            if p1[u] == x {
                up[x] = max(up[u], d2[u])+1
            } else {
                up[x] = max(up[u], d1[u])+1
            }
            dfs2(x, u)
        }
    }
    
    func max(a, b int) int {
        if a > b {
            return a
        } else {
            return b
        }
    }
    
    func min(a, b int) int {
        if a < b {
            return a
        } else {
            return b
        }
    }
    
  • 相关阅读:
    TranslateAnimation 运行动画后实际位置不正确问题
    Linux下如何编译并运行C程序
    row_number() OVER (PARTITION BY COL1 ORDER BY COL2)
    C++软件开发常用辅助软件——gprof
    C++软件开发常用辅助软件——Cppcheck
    C++软件开发常用辅助软件——SCons
    C++软件开发常用辅助软件——Valgrind
    救援linux
    C/C++代码覆盖率生成
    排列的逆
  • 原文地址:https://www.cnblogs.com/ganshuoos/p/14070210.html
Copyright © 2011-2022 走看看