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
    }
}
posted @ 2020-12-01 19:19  ganshuoos  阅读(106)  评论(0编辑  收藏  举报