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

算法题 二叉树的完全性检验

二叉树的完全性检验

问题描述

给定一个二叉树的根节点root,判断该二叉树是否为完全二叉树

完全二叉树定义
在完全二叉树中,除了最底层外,其他层都被完全填满,并且所有结点都尽可能地向左集中。最底层的结点可以不满,但必须从左到右连续排列,不能有“空洞”。

示例

输入: [1,2,3,4,5,6] 输出: true 解释: 所有层都被完全填满,是完全二叉树。 输入: [1,2,3,4,5,null,7] 输出: false 解释: 最底层右边有空洞(6的位置为空,但7存在),不是完全二叉树。

算法思路

层序遍历(BFS)

  1. 使用队列进行层序遍历
  2. 遇到第一个null节点后,后续所有节点都必须是null
  3. 如果在遇到null后又遇到非null节点,说明存在空洞,不是完全二叉树

代码实现

方法一:层序遍历

importjava.util.*;/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode() {} * TreeNode(int val) { this.val = val; } * TreeNode(int val, TreeNode left, TreeNode right) { * this.val = val; * this.left = left; * this.right = right; * } * } */classSolution{/** * 判断二叉树是否为完全二叉树 * * @param root 二叉树根节点 * @return 如果是完全二叉树返回true,否则返回false */publicbooleanisCompleteTree(TreeNoderoot){if(root==null){returntrue;}Queue<TreeNode>queue=newLinkedList<>();queue.offer(root);booleanfoundNull=false;// 标记是否遇到了第一个null节点while(!queue.isEmpty()){TreeNodenode=queue.poll();if(node==null){// 遇到null节点,标记为已发现nullfoundNull=true;}else{// 如果之前已经遇到过null,现在又遇到非null节点// 说明存在空洞,不是完全二叉树if(foundNull){returnfalse;}// 将左右子节点加入队列(包括null节点)queue.offer(node.left);queue.offer(node.right);}}returntrue;}}

方法二:节点编号

importjava.util.*;classSolution{/** * 基于节点编号验证完全二叉树 * 完全二叉树按层序遍历编号时,节点编号应该是连续的1,2,3,...,n * * @param root 二叉树根节点 * @return 如果是完全二叉树返回true,否则返回false */publicbooleanisCompleteTree(TreeNoderoot){if(root==null){returntrue;}Queue<TreeNode>queue=newLinkedList<>();Queue<Integer>indices=newLinkedList<>();// 存储对应节点的编号queue.offer(root);indices.offer(1);// 根节点编号为1intcount=0;// 实际节点数量intlastIdx=0;// 最后一个节点的编号while(!queue.isEmpty()){TreeNodenode=queue.poll();intidx=indices.poll();count++;lastIdx=idx;if(node.left!=null){queue.offer(node.left);indices.offer(idx*2);// 左子节点编号为父节点编号*2}if(node.right!=null){queue.offer(node.right);indices.offer(idx*2+1);// 右子节点编号为父节点编号*2+1}}// 如果是完全二叉树,最后一个节点的编号应该等于总节点数returnlastIdx==count;}}

算法分析

  • 时间复杂度:O(n)
    • 两种方法都需要遍历所有节点一次
  • 空间复杂度:O(w)
    • w 为二叉树的最大宽度,最坏情况下为 O(n)(完全二叉树最后一层)

算法过程

输入[1,2,3,4,5,null,7]

方法一:

  1. 队列初始:[1]foundNull = false
  2. 处理节点1:加入子节点[2,3]foundNull = false
  3. 处理节点2:加入子节点[4,5],队列变为[3,4,5]
  4. 处理节点3:加入子节点[null,7],队列变为[4,5,null,7]
  5. 处理节点4:加入子节点[null,null],队列变为[5,null,7,null,null]
  6. 处理节点5:加入子节点[null,null],队列变为[null,7,null,null,null,null]
  7. 处理nullfoundNull = true
  8. 处理节点7:此时foundNull = true且遇到非null节点,返回false

方法二:

  1. 节点1:编号1,count=1,lastIdx=1
  2. 节点2:编号2,count=2,lastIdx=2
  3. 节点3:编号3,count=3,lastIdx=3
  4. 节点4:编号4,count=4,lastIdx=4
  5. 节点5:编号5,count=5,lastIdx=5
  6. 节点7:编号7,count=6,lastIdx=7
  7. 验证:lastIdx(7) != count(6),返回false

测试用例

publicclassTestCompleteBinaryTree{// 构建测试用的二叉树工具方法privatestaticTreeNodebuildTree(Integer[]arr){if(arr==null||arr.length==0||arr[0]==null){returnnull;}TreeNoderoot=newTreeNode(arr[0]);Queue<TreeNode>queue=newLinkedList<>();queue.offer(root);inti=1;while(!queue.isEmpty()&&i<arr.length){TreeNodenode=queue.poll();if(i<arr.length&&arr[i]!=null){node.left=newTreeNode(arr[i]);queue.offer(node.left);}i++;if(i<arr.length&&arr[i]!=null){node.right=newTreeNode(arr[i]);queue.offer(node.right);}i++;}returnroot;}publicstaticvoidmain(String[]args){Solutionsolution=newSolution();// 测试用例1:完全二叉树Integer[]tree1={1,2,3,4,5,6};System.out.println("Test 1: "+solution.isCompleteTree(buildTree(tree1)));// true// 测试用例2:非完全二叉树(有空洞)Integer[]tree2={1,2,3,4,5,null,7};System.out.println("Test 2: "+solution.isCompleteTree(buildTree(tree2)));// false// 测试用例3:单节点Integer[]tree3={1};System.out.println("Test 3: "+solution.isCompleteTree(buildTree(tree3)));// true// 测试用例4:只有左子树Integer[]tree4={1,2,null,4,5};System.out.println("Test 4: "+solution.isCompleteTree(buildTree(tree4)));// false// 测试用例5:满二叉树Integer[]tree5={1,2,3,4,5,6,7};System.out.println("Test 5: "+solution.isCompleteTree(buildTree(tree5)));// true// 测试用例6:空树Integer[]tree6={};System.out.println("Test 6: "+solution.isCompleteTree(buildTree(tree6)));// true// 测试用例7:只有右子树Integer[]tree7={1,null,3,null,7};System.out.println("Test 7: "+solution.isCompleteTree(buildTree(tree7)));// false}}

关键点

  1. 完全二叉树

    • 层序遍历中不能有"空洞"
    • 一旦出现null,后续必须全部为null
  2. 层序遍历

    • 必须按层从左到右遍历
    • 需要将null节点也加入队列进行处理
  3. 边界情况处理

    • 空树被认为是完全二叉树
    • 单节点树是完全二叉树
    • 只有左子树的树可能是完全二叉树,只有右子树的一定不是

常见问题

  1. 为什么需要将 null 节点加入队列?

    • 为了检测空洞,必须知道在什么位置出现了 null,以及 null 之后是否还有非 null 节点。
  2. 完全二叉树和满二叉树的区别?

    • 满二叉树:所有层都完全填满
    • 完全二叉树:除最后一层外都填满,最后一层从左到右连续
http://www.jsqmd.com/news/275957/

相关文章:

  • 192S04M0131A分布式控制系统
  • 2026年第一季度工业烘干机生产厂家综合评估报告
  • 用Qwen-Image打造海报设计工具,中文排版一步到位
  • 如何将照片从 Pixel 传输到计算机 [实用指南]
  • 学生党如何跑动GPEN?低配GPU显存优化实战技巧
  • R6581T高级数字多媒体
  • 算法题 在长度 2N 的数组中找出重复 N 次的元素
  • 为什么Qwen3-1.7B调用失败?LangChain接入避坑指南
  • 有全局感受野的傅里叶卷积块用于MRI重建/文献速递-基于人工智能的医学影像技术
  • Qwen3Guard-Gen-WEB数据隔离:私有化部署实战
  • 算法题 最大宽度坡
  • unet image Face Fusion跨域问题解决?CORS配置正确姿势
  • 江苏硕晟LIMS pro3.0:引领实验室信息管理新高度
  • Java Web mvc高校办公室行政事务管理系统系统源码-SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0【含文档】
  • Qwen3-Embedding-0.6B与text-embedding-ada-002对比评测
  • 用Qwen3-0.6B做的第一个AI项目——新闻分类器上线
  • Z-Image-Turbo支持哪些格式?PNG转换技巧分享
  • SpringBoot+Vue 在线问卷调查系统管理平台源码【适合毕设/课设/学习】Java+MySQL
  • fft npainting lama日志轮转配置:避免磁盘空间耗尽最佳实践
  • Qwen3-1.7B vs Phi-3-mini:端侧部署可行性对比评测
  • Qwen3-1.7B跨境电商应用:多语言商品描述生成
  • 计算机毕业设计springboot大学生兼职信息管理系统 基于SpringBoot的高校学生兼职岗位智能撮合平台 面向校园的兼职资源一站式管理与匹配系统
  • Qwen-Image-2512-ComfyUI文旅宣传应用:景区海报自动生成系统
  • Arbess项目实战 - 基于GitHub实现Java项目构建并自动化Docker部署
  • Python系列Bug修复|如何解决 pip install 安装报错 ModuleNotFoundError: No module named ‘catboost’ 问题
  • 计算机毕业设计springboot大学生健康管理系统 基于SpringBoot的高校学生身心健康追踪与干预平台 校园健康云:面向大学生的智能健康档案与风险预警系统
  • GPT-OSS部署成本分析:vGPU资源使用优化建议
  • Python系列Bug修复|如何解决 pip install 安装报错 ModuleNotFoundError: No module named ‘lightgbm’ 问题
  • Python系列Bug修复|如何解决 pip install 安装报错 ModuleNotFoundError: No module named ‘xgboost’ 问题
  • Python系列Bug修复|如何解决 pip install 安装报错 ModuleNotFoundError: No module named ‘cudf’ 问题