二叉树
解决关于二叉树的算法题通常可以通过递归或迭代的方式来处理。二叉树的问题大多可以归类为以下几种类型:
- 遍历问题:前序(根-左-右)、中序(左-根-右)、后序(左-右-根)和层次遍历。
- 属性问题:比如计算树的高度、判断二叉树是否平衡等。
- 路径问题:比如寻找从根到叶子的路径之和等。
- 结构问题:比如翻转二叉树、合并二叉树等。
- 动态规划问题:比如二叉树中的最大路径和。
下面我会给出几个 Go 语言的代码实例来说明这些通用思路。
1. 遍历问题 - 中序遍历
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
func inorderTraversal(root *TreeNode) []int {
var res []int
var inorder func(node *TreeNode)
inorder = func(node *TreeNode) {
if node == nil {
return
}
inorder(node.Left)
res = append(res, node.Val)
inorder(node.Right)
}
inorder(root)
return res
}
2. 属性问题 - 计算树的高度
func maxDepth(root *TreeNode) int {
if root == nil {
return 0
}
leftDepth := maxDepth(root.Left)
rightDepth := maxDepth(root.Right)
if leftDepth > rightDepth {
return leftDepth + 1
}
return rightDepth + 1
}
3. 路径问题 - 根到叶子的路径之和
func hasPathSum(root *TreeNode, sum int) bool {
if root == nil {
return false
}
if root.Left == nil && root.Right == nil {
return sum == root.Val
}
return hasPathSum(root.Left, sum-root.Val) || hasPathSum(root.Right, sum-root.Val)
}
4. 结构问题 - 翻转二叉树
func invertTree(root *TreeNode) *TreeNode {
if root == nil {
return nil
}
root.Left, root.Right = invertTree(root.Right), invertTree(root.Left)
return root
}
5. 动态规划问题 - 二叉树中的最大路径和
func maxPathSum(root *TreeNode) int {
maxSum := math.MinInt32
var maxGain func(node *TreeNode) int
maxGain = func(node *TreeNode) int {
if node == nil {
return 0
}
leftGain := max(0, maxGain(node.Left))
rightGain := max(0, maxGain(node.Right))
priceNewpath := node.Val + leftGain + rightGain
maxSum = max(maxSum, priceNewpath)
return node.Val + max(leftGain, rightGain)
}
maxGain(root)
return maxSum
}
func max(x, y int) int {
if x > y {
return x
}
return y
}
在解决二叉树的问题时,递归是一种非常自然和强大的方法,因为二叉树本身的结构就是递归定义的。迭代方法通常需要使用栈来模拟递归过程。在实际编码时,应该选择最适合问题的方法。