当前位置: 首页 > news >正文

110. 平衡二叉树

文章目录

  • 110. 平衡二叉树
    • 题外话
  • 本题思路
    • 递归

110. 平衡二叉树

110. 平衡二叉树

给定一个二叉树,判断它是否是 平衡二叉树

平衡二叉树 是指该树所有节点的左右子树的深度相差不超过 1

示例 1:

输入:root = [3,9,20,null,null,15,7]
输出:true

示例 2:

输入:root = [1,2,2,3,3,null,null,4,4]
输出:false

示例 3:

输入:root = []
输出:true

提示:

  • 树中的节点数在范围 [0, 5000] 内
  • -10^4 <= Node.val <= 10^4

题外话

咋眼一看这道题目和104. 二叉树的最大深度(包括N叉树的最大深度)很像,其实有很大区别。

这里强调一波概念:

  • 二叉树节点的深度:指从根节点该节点的最长简单路径边的条数。
  • 二叉树节点的高度:指从该节点叶子节点的最长简单路径边的条数。

leetcode中强调的深度和高度很明显是按照节点来计算的,如图:
在这里插入图片描述

关于根节点的深度究竟是1 还是 0,不同的地方有不一样的标准,leetcode的题目中都是以节点为一度,即根节点深度是1。但维基百科上定义用边为一度,即根节点的深度是0,我们暂时以leetcode为准(毕竟要在这上面刷题)。

因为求深度可以从上到下去查 所以需要前序遍历(中左右),而高度只能从下到上去查,所以只能后序遍历(左右中) ,可以理解为深度是从上往下不断增加,而高度是从下往上不断增加。

有的同学一定疑惑,为什么104.二叉树的最大深度 中求的是二叉树的最大深度,也用的是后序遍历。

那是因为代码的逻辑其实是求的根节点的高度,而根节点的高度就是这棵树的最大深度,所以才可以使用后序遍历。如果是求某个中间节点的深度,则使用后序遍历可能会算错,比如上图中节点4的深度是3,如果按后序遍历求高度来算,会得到深度是2(但深度实际是3,高度才是2)

104.二叉树的最大深度 中,如果真正求取二叉树的最大深度,Go代码应该写成如下:(前序遍历)

/*** Definition for a binary tree node.* type TreeNode struct {*     Val int*     Left *TreeNode*     Right *TreeNode* }*/
func maxDepth(root *TreeNode) int {if root == nil {return 0}// 使用前序遍历,不断更新最大深度的变量值res := 1dfs(root,1,&res)return res
}func dfs(root *TreeNode,depth int,res *int)  {if *res < depth { // 中*res = depth}if root.Left != nil { // 左depth += 1 // 深度+1dfs(root.Left,depth,res)depth -= 1 // 回溯,深度-1}if root.Right != nil { // 右depth += 1 // 深度+1dfs(root.Right,depth,res)depth -= 1 // 回溯,深度-1}}

可以看出使用了前序(中左右)的遍历顺序,这才是真正求深度的逻辑!

注意以上代码是为了把细节体现出来,简化一下代码如下:

/*** Definition for a binary tree node.* type TreeNode struct {*     Val int*     Left *TreeNode*     Right *TreeNode* }*/
func maxDepth(root *TreeNode) int {if root == nil {return 0}// 使用前序遍历,不断更新最大深度的变量值res := 1dfs(root,1,&res)return res
}func dfs(root *TreeNode,depth int,res *int)  {if *res < depth { // 中*res = depth}if root.Left != nil { // 左dfs(root.Left,depth + 1,res)}if root.Right != nil { // 右dfs(root.Right,depth + 1,res)}}

本题思路

递归

此时大家应该明白了既然要求比较高度,必然是要后序遍历

递归三步曲分析:

  1. 明确递归函数的参数和返回值
    参数:当前传入节点。 返回值:当前节点为根的树是否是平衡二叉树
func isBalanced(root *TreeNode) bool {}
  1. 明确递归终止条件
    递归的过程中依然是遇到空节点了为终止,返回true,表示空节点可以当成平衡二叉树。另一个递归终止条件时,当前树已经明确不是平衡二叉树的时候,没必要继续往后继续递归了,而是应该往上层调用栈回归了。

代码如下:

    if root == nil {return true}// 左右子树高度绝对值相差大于1可以直接返回false了if int(math.Abs(float64(getDepth(root.Left) - getDepth(root.Right)))) > 1 {return false}
  1. 明确单层递归的逻辑
    当前根节点的左子树和右子树均为平衡二叉树

代码如下:

	left := isBalanced(root.Left)  // 左right := isBalanced(root.Right) // 右res := left && right // 根

最后本题整体递归代码如下:

Go代码

/*** Definition for a binary tree node.* type TreeNode struct {*     Val int*     Left *TreeNode*     Right *TreeNode* }*/
func isBalanced(root *TreeNode) bool {// 以每一个节点作为根节点,判断他的左右子树高度之差是否小于等于1if root == nil {return true}// 左右子树高度绝对值相差大于1可以直接返回false了if int(math.Abs(float64(getDepth(root.Left) - getDepth(root.Right)))) > 1 {return false}left := isBalanced(root.Left)  // 左right := isBalanced(root.Right) // 右res := left && right // 根return res
}// 求二叉树最大深度的模板代码
func getDepth(root *TreeNode) int{if root == nil {return 0}return max(getDepth(root.Left),getDepth(root.Right)) + 1
}func max(a,b int) int {if a > b {return a}return b
}

在这里插入图片描述


http://www.mrgr.cn/news/33747.html

相关文章:

  • 高等数学——微分学
  • Linux:终端(terminal)与终端管理器(agetty)
  • 学习记录:js算法(四十一): 基于时间的键值存储
  • 鸿蒙OpenHarmony【轻量系统内核扩展组件(CPU占用率)】子系统开发
  • sftp登录ipv6用中括号 `sftp x@[ipv6]`
  • 2D目标检测常用loss
  • [Excel VBA]如何使用VBA自动生成图表
  • iOS 中 KVC 与 KVO 底层原理
  • 面试题(二)
  • Java--File
  • 【详细解答】指出下面指令的错误:IN AL,300H
  • 2024年 5 个优秀的Flutter图标库
  • CSS 选择器的分类与使用要点二
  • linux中vim编辑器的应用实例
  • 在Spring Boot中实现多环境配置
  • weak_from_this
  • 信息安全技术基础知识
  • vscode 顶部 Command Center,minimap
  • RuntimeError: Maximum Recursion Depth Exceeded - 递归深度超限的完美解决方案
  • uniapp自定义Tabbar教程