這裏我們可以採用很多解法,比如單隊列、雙隊列、但更多的,我覺得采用遞歸思想,纔是比較考驗思維功底的。
解法一:非遞歸-雙隊列解法
首先來一個通用的非遞歸解法,採用雙隊列比單隊列好理解,而且更高效。我的寫法參考如下,見註釋部分:
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func maxLevelSum(root *TreeNode) int {
if root == nil {
return 0
}
queue := []*TreeNode{root}
maxSum := 0
level := 0
res := level
for len(queue)>0 {
// 記錄每一層
level++
// 準備開始求和
sum := 0
// 先創建一個隊列來存子節點,並重置爲0,來重新開始
newQueue := make([]*TreeNode, 0)
// 計算每一層
for _, v := range queue {
sum += v.Val
if v.Left != nil {
newQueue = append(newQueue, v.Left)
}
if v.Right != nil {
newQueue = append(newQueue, v.Right)
}
}
// 保留當前節點和最大值的層
if maxSum < sum {
maxSum = sum
res = level
}
// 指向子隊列
queue = newQueue
}
return res
}
解法二:遞歸思想
像這種,我覺得還是遞歸思想更加能得到鍛鍊,我現分享如下的兩種遞歸解法,僅供參考,具體請見註釋部分。
/**
蠻力算法思路就是超級簡單,當然效率一般,因爲很多步驟重複了:
1、計算樹有多少層。
2、計算每一層的和
3、從樹的根到葉,一層層求最大值
4、輸出最大值
*/
func myMax(x, y int) int{
if x>y {
return x
}
return y
}
func maxLevelSum(root *TreeNode) int {
if root==nil {
return 0
}
sum := 0
maxDepth := getMaxDepth(root)
res := 0
for i:=0; i<maxDepth; i++ {
curlevelSum := getLevelSum(root, i)
if curlevelSum > sum {
sum = curlevelSum
res = i
}
}
return res+1
}
// 計算深度
func getMaxDepth(root *TreeNode) int {
if root==nil {
return 0
}
return myMax(getMaxDepth(root.Left)+1, getMaxDepth(root.Right)+1)
}
// 計算單層的元素累積和
func getLevelSum(root *TreeNode, level int) int {
if root==nil || level<0 {
return 0
}
if level==0 {
return root.Val
}
return getLevelSum(root.Left, level-1) + getLevelSum(root.Right, level-1)
}
解法二:這種思路也很清晰,而且寫出的代碼優美不冗餘。
// 主要思想
// 爲每一層維護一個和值 rowSum,然後比較各層和最大值,將其輸出
// 具體看代碼註釋
func maxLevelSum(root *TreeNode) int {
var rowSum []int
maxSum, maxLevel := math.MinInt32, -1
dfs(root, &rowSum, 0)
for i, sum := range rowSum {
if sum > maxSum {
maxSum = sum
maxLevel = i
}
}
return maxLevel + 1
}
func dfs(root *TreeNode, rowSum *[]int, depth int) {
if root == nil {
return
}
// 只要是要入棧的元素大於它所在的深度,說明此時該層已經有元素了,
// 此時,來一個,累加一個,放在depth索引所在的位置。
// 我們只需要將其所在層的這些值挨個進行累加即可。
if len(*rowSum) > depth {
(*rowSum)[depth] += root.Val
} else { // 否則,說明還沒有對應depth索引位置的元素出現,那就入棧吧
*rowSum = append(*rowSum, root.Val)
}
// 最後,分別對左右子樹進行遞歸吧
dfs(root.Left, rowSum, depth+1)
dfs(root.Right, rowSum, depth+1)
}