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

Day15--二叉树--222. 完全二叉树的节点个数,110. 平衡二叉树,257. 二叉树的所有路径,404. 左叶子之和

Day15–二叉树–222. 完全二叉树的节点个数,110. 平衡二叉树,257. 二叉树的所有路径,404. 左叶子之和

222. 完全二叉树的节点个数

思路参考自:完全二叉树的节点数,你真的会算吗?

参考二:《代码随想录》:

完全二叉树只有两种情况,情况一:就是满二叉树,情况二:最后一层叶子节点没有满。

对于情况一,可以直接用 2^树深度 - 1 来计算,注意这里根节点深度为1。

对于情况二,分别递归左孩子,和右孩子,递归到某一深度一定会有左孩子或者右孩子为满二叉树,然后依然可以按照情况1来计算。

这里关键在于如何去判断一个左子树或者右子树是不是满二叉树呢?

在完全二叉树中,如果递归向左遍历的深度等于递归向右遍历的深度,那说明就是满二叉树。

思路:完全二叉树,它的左右子树,其中至少有一颗是满二叉树。满二叉树直接根据公式计算,另一颗按照普通二叉树计算。

//  完全二叉树,它的左右子树,其中至少有一颗是满二叉树。
//  满二叉树直接根据公式计算,另一颗按照普通二叉树计算。
//  对于“不是满二叉树”的那颗子树,往下遍历的时候,也可能会有“满二叉树”的情况
//  本代码优化的速度就在于,凡是“满二叉树”就套公式。
class Solution {public int countNodes(TreeNode root) {// 其实这种就一句话的函数,是可以直接写在调用方法里的。// 多写一个方法是因为,这里的节点叫root,容易误解。叫node容易理解。return getNodeNum(root);}private int getNodeNum(TreeNode node) {// 基本上所有代码就是为了“判断是否是满二叉树”if(node==null){return 0;}// 分左右子树TreeNode left = node.left;TreeNode right = node.right;// 记录左右子树的高度// 初始化为1是因为,判断左右子树是否高度相等,是在cur本节点判断的// 如果成立,证明从本节点开始就是满二叉树,要加上本层int leftHeight = 1;int rightHeight = 1;// 统计高度while (left != null) {left = left.left;leftHeight++;}while (right != null) {right = right.right;rightHeight++;}// 如果左右子树高度相同,是一颗满二叉树,可以直接根据公式计算if (leftHeight == rightHeight) {return (int) Math.pow(2, leftHeight) - 1;}// 如果不是满二叉树,则按照普通二叉树的逻辑计算return countNodes(node.left) + countNodes(node.right) + 1;}
}

思路:

递归法:完全当成普通二叉树来算

class Solution {public int countNodes(TreeNode root) {return getNodesNum(root);}private int getNodesNum(TreeNode node) {// 节点为空,返回0if (node == null) {return 0;}// 递归左子树int leftNum = getNodesNum(node.left);// 递归右子树int rightNum = getNodesNum(node.right);// 子树节点+1(自身)->返回给上一层int curNum = leftNum + rightNum + 1;return curNum;}
}

110. 平衡二叉树

思路:

  • 后序遍历法:自底向上统计
  • 如果高度差大于1,返回-1做标记给上层
  • 每一层算高度的时候:取左右子树之中的max,然后+1,当做是本层的高度(因为高度是自底向上算的)
//  后序遍历法:自底向上统计
class Solution {public boolean isBalanced(TreeNode root) {return getHeight(root) == -1 ? false : true;}private int getHeight(TreeNode node) {if (node == null) {return 0;}int leftHeight = getHeight(node.left);int rightHeight = getHeight(node.right);// 如果下层返回的有-1,直接返回-1给上层if (leftHeight == -1 || rightHeight == -1) {return -1;}// 如果高度差大于1,返回-1做标记给上层if (Math.abs(leftHeight - rightHeight) > 1) {return -1;}// 取左右子树之中的max,然后+1,当做是本层的高度(因为高度是自底向上算的)return Math.max(leftHeight, rightHeight) + 1;}
}

257. 二叉树的所有路径

思路:后序遍历:自下而上传递字符串,把孩子传上的字符串拼接本层,加工后传给上一层

// 后序遍历:自下而上传递字符串,把孩子传上的字符串拼接本层,加工后传给上一层
class Solution {public List<String> binaryTreePaths(TreeNode root) {return getChildrenString(root);}private List<String> getChildrenString(TreeNode node) {List<String> list = new ArrayList<>();if (node == null) {return list;}// 拼接左节点传上来的字符串if (node.left != null) {List<String> leftList = getChildrenString(node.left);// 每一个字符串,都要加上本节点的val和"->"// 然后重新加到本节点的list里,每一个node都会新一个listfor (String s : leftList) {String temp = node.val + "->" + s;list.add(temp);}}// 拼接右节点传上来的字符串if (node.right != null) {List<String> rightList = getChildrenString(node.right);for (String s : rightList) {String temp = node.val + "->" + s;list.add(temp);}}// 如果是叶子节点,直接返回本节点的val的字符串形式if (node.left == null && node.right == null) {list.add("" + node.val);}return list;}
}

404. 左叶子之和

思路:

递归遍历。要保证node.left是个叶子,才要它的值。

class Solution {public int sumOfLeftLeaves(TreeNode root) {return getLeftSum(root);}private int getLeftSum(TreeNode node) {int leftNodeSum = 0;int rightNodeSum = 0;if (node.right != null) {rightNodeSum = getLeftSum(node.right);}if (node.left != null) {leftNodeSum = getLeftSum(node.left);// 要保证node.left是个叶子,才要它的值if (node.left.left == null && node.left.right == null) {return leftNodeSum + rightNodeSum + node.left.val;}}return leftNodeSum + rightNodeSum;}
}
http://www.lryc.cn/news/605634.html

相关文章:

  • 在Linux中创建LVGL应用
  • Kotlin -> 普通Lambda vs 挂起Lambda
  • 【Django】-1- 开发项目搭建
  • Django模型迁移指南:从命令用法到最佳实践
  • HttpServletRequest详细解释
  • 如何在NPM上发布自己的React组件(包)
  • 人工智能概念之十一:常见的激活函数与参数初始化
  • Cesium 快速入门(四)相机控制完全指南
  • langchain--1--prompt、output格式、LCEL示例
  • 【烧脑算法】Dijkstra 算法:解决最短路问题
  • 会议室预定系统核心技术:如何用一行SQL解决时间冲突检测难题
  • LLC电源原边MOS管DS增加RC吸收对ZVS的影响分析
  • ode with me是idea中用来干嘛的插件
  • 山东移动云主机:技术架构与特性解析
  • AI 安监系统:为工业园安全保驾护航
  • 1 机器学习概述 (第一天2025.7.31)
  • RabbitMQ 队列配置设置 RabbitMQ 消息监听器的并发消费者数量java
  • Java 大视界 -- Java 大数据在智能医疗远程健康监测与疾病预防预警中的应用(374)
  • Linux 进程管理与计划任务
  • linux git ssh配置过程
  • React中的this绑定
  • SpringMVC的核心架构与请求处理流程
  • PostgreSQL dblink 与 Spring Boot @Transactional 的事务整合
  • 网络层概述
  • AngularJS 事件
  • Web 开发 08
  • 智慧社区项目开发(四)——前后端登录认证相关功能实现解析
  • 网关 + MDC 过滤器方案,5分钟集成 日志 traceid
  • Gemini Fullstack LangGraph Quickstart(DeepSeek+Tavily版本)
  • 智慧园区通行效率↑68%!陌讯多模态融合算法的实战解析