目录
[1 问题描述](#1 问题描述)
[1.1 示例1](#1.1 示例1)
[1.2 示例2](#1.2 示例2)
[1.3 示例3](#1.3 示例3)
[2 解题思路](#2 解题思路)
[3 代码实现](#3 代码实现)
[4 代码解析](#4 代码解析)
[4.1 定义队列,初始化根节点](#4.1 定义队列,初始化根节点)
[4.2 层序遍历,处理每个节点](#4.2 层序遍历,处理每个节点)
[4.3 处理空节点](#4.3 处理空节点)
[4.4 处理非空节点](#4.4 处理非空节点)
[5 总结](#5 总结)
1 问题描述
给定一个二叉树,确定他是否是一个完全二叉树。
完全二叉树的定义:若二叉树的深度为 h,除第 h 层外,其它各层的结点数都达到最大个数,第 h 层所有的叶子结点都连续集中在最左边,这就是完全二叉树。(第 h 层可能包含 [1~2h] 个节点)
数据范围:节点数满足 1≤n≤100 1≤n≤100
样例图1:

样例图2:

样例图3:

1.1 示例1
输入:
{1,2,3,4,5,6}
返回值:
true
1.2 示例2
输入:
{1,2,3,4,5,6,7}
返回值:
true
1.3 示例3
输入:
{1,2,3,4,5,#,6}
返回值:
false
2 解题思路
采用层序遍历(BFS)方式,通过队列 queue<TreeNode*>
进行逐层扫描。首先将根节点入队,然后依次出队检查其左右子节点。关键在于一个布尔变量 mustBeLeaf
,用于标识是否已经遇到 nullptr
,即是否应该只允许叶子节点(空节点)出现。当 nullptr
出现后,若后续仍有非空节点,则说明该树不是完全二叉树,返回 false
;否则,遍历结束返回 true
。这样保证了若某层的节点不满,则该层之后不能再有非空节点,从而正确判断完全二叉树的性质。
3 代码实现
cpp
bool isCompleteTree(TreeNode* root) {
// write code here
if (root == nullptr) return true;
queue<TreeNode*> q;
q.push(root);
bool mustBeLeaf = false;
while (!q.empty()) {
TreeNode* node = q.front();
q.pop();
if (mustBeLeaf)
{
if (node != nullptr) return false;
}
else {
if (node == nullptr)
{
mustBeLeaf = true;
}
else {
q.push(node->left);
q.push(node->right);
}
}
}
return true;
}
4 代码解析
4.1 定义队列,初始化根节点
cpp
if (root == nullptr) return true;
queue<TreeNode*> q;
q.push(root);
bool mustBeLeaf = false;
首先,代码检查根节点是否为空,若为空,则直接返回 true
,因为空树是完全二叉树。然后,定义一个队列 q
,用于进行层序遍历(BFS),并将根节点 root
入队。变量 mustBeLeaf
用于标记是否遇到了空节点,一旦为 true
,后续所有节点必须为空,否则就不是完全二叉树。
4.2 层序遍历,处理每个节点
cpp
while (!q.empty()) {
TreeNode* node = q.front();
q.pop();
使用 while
循环进行层序遍历,每次从队列 q
中取出队首节点 node
。如果 q
为空,说明遍历完成,跳出循环。
4.3 处理空节点
cpp
if (mustBeLeaf)
{
if (node != nullptr) return false;
}
如果 mustBeLeaf
为 true
,说明之前已经遇到了空节点,那么所有后续节点都必须为空。如果当前节点 node
不是空节点,则说明二叉树不是完全二叉树,直接返回 false
。
4.4 处理非空节点
cpp
else {
if (node == nullptr)
{
mustBeLeaf = true;
}
else {
q.push(node->left);
q.push(node->right);
}
}
如果 mustBeLeaf
仍为 false
,则说明当前节点还可以是非空的。如果当前节点 node
是 nullptr
,则将 mustBeLeaf
设为 true
,意味着之后所有节点必须为空。如果当前节点 node
不是 nullptr
,则继续将 node->left
和 node->right
依次入队,即继续层序遍历子节点。
5 总结
通过队列依次遍历每个节点,并使用布尔变量 mustBeLeaf
来标记是否已经遇到空节点,确保一旦出现 nullptr
,后续所有节点都必须为空,否则返回 false
。该方法能有效检测是否存在不连续的叶子节点,从而正确判断完全二叉树的性质。整个算法的时间复杂度为 O(n) ,空间复杂度为 O(n) ,适用于 n ≤ 100
的数据范围,能够高效解决问题。