二叉树的最大深度定义是:从根节点到最远叶子节点的最长路径上的节点数
对于平衡二叉树来说,每个节点的左、右子树深度相差都不超过1,那么也可以理解为每个节点的左、右子树最大深度相差不超过1。
解法一:暴力法
关于计算一棵二叉树最大深度,可以参考之前这道题
暴力思路一般是:遍历二叉树,然后对每一个节点计算左、右子树的最大高度,但是计算一棵二叉树的最大深度也需要递归遍历这棵树的所有节点,如果对每个节点都要算一遍最大深度,时间复杂度是比较高的。类比这道题
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func isBalanced(root *TreeNode) bool {
if root == nil{
return true
}
isBalanced := true
traverse(root, &isBalanced)
return isBalanced
}
func traverse(root *TreeNode, isBalanced *bool){
if root == nil{
return
}
if !*isBalanced{ // 有个节点不平衡,直接短路径返回
return
}
// 每个节点,求左、右子树的最大深度
leftMaxDepth := maxDepth(root.Left)
rightMaxDepth := maxDepth(root.Right)
// 判断左右子数是否高度相差>1
if abs(leftMaxDepth - rightMaxDepth) > 1{
*isBalanced = false
}
traverse(root.Left, isBalanced)
traverse(root.Right, isBalanced)
}
func maxDepth(root *TreeNode) int{
if root == nil{
return 0
}
leftMax := maxDepth(root.Left)
rightMax := maxDepth(root.Right)
return max(leftMax, rightMax) + 1
}
func max(a, b int) int{
if a > b{
return a
}
return b
}
func abs(x int) int{
if x < 0{
return -x
}
return x
}
另一种写法,也是前序遍历思想
func isBalanced(root *TreeNode) bool {
if root == nil{
return true
}
leftMaxDepth := maxDepth(root.Left)
rightMaxDepth := maxDepth(root.Right)
// 当前根节点满足左右子树深度相差不超过1,并且左右子节点也要满足该特性
return abs(leftMaxDepth - rightMaxDepth) <= 1 && isBalanced(root.Left) && isBalanced(root.Right)
}
func maxDepth(root *TreeNode) int{
if root == nil{
return 0
}
leftMax := maxDepth(root.Left)
rightMax := maxDepth(root.Right)
return max(leftMax, rightMax) + 1
}
func max(a, b int) int{
if a > b{
return a
}
return b
}
func abs(x int) int{
if x < 0{
return -x
}
return x
}
- 时间复杂度:O(NlogN): 最差情况下(为 “满二叉树” 时),isBalanced(root) 遍历树所有节点,判断每个节点时的深度,每次需要遍历各子树的所有节点,会存在重复的节点遍历。
- 空间复杂度:O(N),
那么,如何才能只计算一次最大深度呢?
反过来思考,计算的过程中在后序遍历位置顺便判断二叉树是否平衡,因为 maxDepth 的后序位置是知道当前入参节点的左、右子树的最大深度的。
解法二:后序遍历
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func isBalanced(root *TreeNode) bool {
isBalanced := true
maxDepth(root, &isBalanced)
return isBalanced
}
func maxDepth(root *TreeNode, isBalanced *bool) int{
if root == nil{
return 0
}
leftMaxDepth := maxDepth(root.Left, isBalanced)
rightMaxDepth := maxDepth(root.Right, isBalanced)
// 后续遍历位置
if abs(leftMaxDepth - rightMaxDepth) > 1{
// 如果左右子树的深度差>1,就不平衡
*isBalanced = false
}
return max(leftMaxDepth, rightMaxDepth) + 1
}
func max(a, b int) int{
if a > b{
return a
}
return b
}
func abs(x int) int{
if x < 0{
return -x
}
return x
}
- 时间复杂度:O(n),最差情况下,需要遍历树的所有节点才能判断是否每个节点都满足平衡
- 空间复杂度:O(n),递归栈,最差情况下树退化为链表,递归层数等同节点数