news 2026/4/11 22:45:38

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
算法题 二叉树的完全性检验

二叉树的完全性检验

问题描述

给定一个二叉树的根节点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. 完全二叉树和满二叉树的区别?

    • 满二叉树:所有层都完全填满
    • 完全二叉树:除最后一层外都填满,最后一层从左到右连续
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/7 17:49:49

【学习笔记】Transformer基础概念

Transformer每次都听朋友聊到&#xff0c;虽然我目前的研究领域尚未包含这种架构&#xff0c;但是还是学习一下。Transformer 是一种革命性的神经网络架构。它于2017年由谷歌团队的论文《Attention Is All You Need》提出&#xff0c;最初用于机器翻译&#xff0c;但后来彻底改…

作者头像 李华
网站建设 2026/4/10 15:51:02

GPT-OSS部署成本分析:vGPU资源使用优化建议

GPT-OSS部署成本分析&#xff1a;vGPU资源使用优化建议 在当前大模型广泛应用的背景下&#xff0c;GPT-OSS作为OpenAI最新开源的20B参数级别模型&#xff0c;凭借其强大的语言理解与生成能力&#xff0c;正被越来越多企业和开发者用于本地化部署。本文聚焦于gpt-oss-20b-WEBUI…

作者头像 李华
网站建设 2026/3/27 13:45:53

Qwen3-Embedding-0.6B与text-embedding-ada-002对比评测

Qwen3-Embedding-0.6B与text-embedding-ada-002对比评测 1. Qwen3-Embedding-0.6B 模型解析 1.1 核心能力与技术背景 Qwen3 Embedding 模型系列是 Qwen 家族中专为文本嵌入和排序任务打造的最新成员&#xff0c;基于强大的 Qwen3 系列密集基础模型构建。该系列覆盖了从轻量级…

作者头像 李华
网站建设 2026/3/31 16:40:44

提升开发效率:fft npainting lama调试模式启用指南

提升开发效率&#xff1a;fft npainting lama调试模式启用指南 1. 调试模式的价值与适用场景 在进行图像修复类AI应用的二次开发时&#xff0c;最让人头疼的问题之一就是“黑盒运行”——模型跑起来了&#xff0c;但不知道中间发生了什么。尤其是当你基于 fft npainting lama…

作者头像 李华
网站建设 2026/4/11 22:40:30

Windchill PLM软件资产管理成效的绩效考核(KPI)指标体系

Windchill PLM软件资产管理成效的绩效考核&#xff08;KPI&#xff09;指标体系 ——如何量化PLM软件的资产价值与管理成效作为企业数字化转型的重要组成部分&#xff0c;PLM&#xff08;Product Lifecycle Management&#xff09;软件在产品开发流程中的作用日益凸显。软件复杂…

作者头像 李华