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
}
}