news 2026/6/10 19:00:28

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

作者头像

张小明

前端开发工程师

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/6/10 13:37:45

算法题 最大宽度坡

最大宽度坡 问题描述 给定一个整数数组 nums&#xff0c;定义一个坡为元组 (i, j)&#xff0c;其中 i < j 且 nums[i] < nums[j]。坡的宽度为 j - i。 请返回数组中最大宽度坡的宽度。如果没有坡&#xff0c;返回 0。 示例&#xff1a; 输入: [6,0,8,2,1,5] 输出: 4 解释…

作者头像 李华
网站建设 2026/6/10 13:38:02

YOLO11云端部署指南,GPU加速轻松开启

YOLO11云端部署指南&#xff0c;GPU加速轻松开启 你是否还在为搭建YOLO系列模型的复杂环境而头疼&#xff1f;是否希望快速上手最新的YOLO11&#xff0c;直接进入训练和推理阶段&#xff1f;本文将带你一步步完成YOLO11在云端的一键式部署&#xff0c;利用预置镜像实现GPU加速…

作者头像 李华
网站建设 2026/6/10 14:45:43

Arbess项目实战 - 基于GitHub实现Java项目构建并自动化Docker部署

Arbess 是一款国产开源免费的 CI/CD 工具&#xff0c;支持免费自动化部署&#xff0c;一键安装零配置。本文将详细介绍如何安装并使用ArbessGitHub实现Docker项目自动化构建部署 1、GitHub 配置 本章节将介绍如何创建GitHub个人访问令牌&#xff0c;提供给Arbess克隆源码。 …

作者头像 李华