最大層內元素和

在這裏插入圖片描述

這裏我們可以採用很多解法,比如單隊列、雙隊列、但更多的,我覺得采用遞歸思想,纔是比較考驗思維功底的。

解法一:非遞歸-雙隊列解法

首先來一個通用的非遞歸解法,採用雙隊列比單隊列好理解,而且更高效。我的寫法參考如下,見註釋部分:

/**
 * 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)
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章