問(wèn)題定義
如果我們把二叉樹(shù)看成一個(gè)圖,父子節(jié)點(diǎn)之間的連線看成是雙向的,我們姑且定義"距離"為兩節(jié)點(diǎn)之間邊的個(gè)數(shù)。寫(xiě)一個(gè)程序求一棵二叉樹(shù)中相距最遠(yuǎn)的兩個(gè)節(jié)點(diǎn)之間的距離。
image
書(shū)上的解法
書(shū)中對(duì)這個(gè)問(wèn)題的分析是很清楚的,我嘗試用自己的方式簡(jiǎn)短覆述。
計(jì)算一個(gè)二叉樹(shù)的最大距離有兩個(gè)情況:
- 情況A: 路徑經(jīng)過(guò)左子樹(shù)的最深節(jié)點(diǎn),通過(guò)根節(jié)點(diǎn),再到右子樹(shù)的最深節(jié)點(diǎn)。
- 情況B: 路徑不穿過(guò)根節(jié)點(diǎn),而是左子樹(shù)或右子樹(shù)的最大距離路徑,取其大者。
只需要計(jì)算這兩個(gè)情況的路徑距離,并取其大者,就是該二叉樹(shù)的最大距離。
image
type node struct {
data int
left *node
ritht *node
}
type result struct {
nMaxDepth int
nMaxDistance int
}
//情況A對(duì)應(yīng)的數(shù)據(jù)
var p9 = &node{9, nil, nil}
var p8 = &node{8, nil, nil}
var p7 = &node{7, nil, nil}
var p6 = &node{6, nil, p9}
var p5 = &node{5, nil, nil}
var p4 = &node{4, p8, nil}
var p3 = &node{3, p6, p7}
var p2 = &node{2, p4, p5}
var p1 = &node{1, p2, p3}
//情況B對(duì)應(yīng)的數(shù)據(jù)
var n6 = &node{6, nil, nil}
var n5 = &node{5, nil, nil}
var n4 = &node{4, nil, n6}
var n3 = &node{3, n5, nil}
var n2 = &node{2, n3, n4}
var n1 = &node{1, n2, nil}
func getMaxDistance(p *node) result {
if p == nil {
return result{-1, -1} //因?yàn)槿绻挥幸粋€(gè)節(jié)點(diǎn)的時(shí)候,nMaxDepth是0(-1+1),nMaxDistance也是0(-1+-1+2)
}
l := getMaxDistance(p.left)
r := getMaxDistance(p.ritht)
res := result{}
res.nMaxDepth = max(l.nMaxDepth, r.nMaxDepth) + 1
res.nMaxDistance = max(max(l.nMaxDistance, r.nMaxDistance), l.nMaxDepth+r.nMaxDepth+2)
return res
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func main() {
res1 := getMaxDistance(p1)
fmt.Println(res1.nMaxDepth, res1.nMaxDistance)
res2 := getMaxDistance(n1)
fmt.Println(res2.nMaxDepth, res2.nMaxDistance)
}
運(yùn)行結(jié)果:
C:\Users\minping\Desktop>go run 1.go
3 6
3 4
result中的nMaxDepth很簡(jiǎn)單,就是max(left depth, rightdepth) +1 (這也是為什么初始值是result{-1, -1}的原因)
result中的nMaxDistance就比較復(fù)雜一點(diǎn),是l.nMaxDistance, r.nMaxDistance(對(duì)應(yīng)B情況,在左子樹(shù)或者右子樹(shù)中,不跨根節(jié)點(diǎn))和l.nMaxDepth+r.nMaxDepth+2(對(duì)應(yīng)A情況,跨根節(jié)點(diǎn))三者的最大值。仔細(xì)想一想為什么是加2(因?yàn)楦?jié)點(diǎn)和左右子樹(shù)通過(guò)兩條邊連接起來(lái)的,所以+2)