1.题目描述
给定一个二叉树,确定他是否是一个完全二叉树。
完全二叉树的定义:若二叉树的深度为 h,除第 h 层外,其它各层的结点数都达到最大个数,第 h 层所有的叶子结点都连续集中在最左边,这就是完全二叉树。(第 h 层可能包含 [1~2h] 个节点)
数据范围:节点数满足 1≤𝑛≤100 1≤n≤100
样例图1:
样例图2:
样例图3:
示例1
输入:
{1,2,3,4,5,6}复制返回值:
true示例2
输入:
{1,2,3,4,5,6,7}返回值:
true示例3
输入:
{1,2,3,4,5,#,6}返回值:
false
2.解题思路
思路1:深度优先遍历dfs
如果一棵树是完全二叉树,将它的结点按照从上到下,从左到右的顺序编号,一定有如下结论:
假设当前结点编号为i,它的左孩子编号一定为2*i;右孩子编号一定为2 * i + 1
那么我们只需要定义一个成员变量encode,记录遍历过程中的最大编号,再与这个树的结点总数对比,如果两者一致则说明是完全二叉树,不一致,则说明某一层缺少了部分结点,使得这棵树不是完全二叉树
思路2:层序遍历二叉树
如果一棵树是完全二叉树,它在层序遍历时,一定不会出现当前访问到的结点前有空结点的情况,我们只需要借助一个队列,依次遍历当前结点,并把它的左右孩子放到队列中,如果当前访问结点之前队列中出现了空结点,则说明不是完全二叉树,直接返回false;如果能正常遍历结束,则说明是完全二叉树
3.代码实现
思路1:
import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* public TreeNode(int val) {
* this.val = val;
* }
* }
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @return bool布尔型
*/
public int encode = 0;
public boolean isCompleteTree (TreeNode root) {
// write code here
return dfs(root,1) == encode;
}
public int dfs(TreeNode node, int idx) {
if (node == null) return 0;
//给遍历到的编号为i的结点按照left = 2 * i right = 2 * i + 1的规则编号
encode = Math.max(encode,idx);
//返回当前子树总结点个数
return 1 + dfs(node.left,idx*2) + dfs(node.right,idx*2 + 1);
}
}
思路2:
import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* public TreeNode(int val) {
* this.val = val;
* }
* }
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @return bool布尔型
*/
public boolean isCompleteTree (TreeNode root) {
// write code here
if (root == null) return true;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
boolean flag = true;
while (!queue.isEmpty()) {
TreeNode cur = queue.poll();
if (cur == null) {
flag = false;
} else {
if (flag == false) return false;
else {
queue.offer(cur.left);
queue.offer(cur.right);
}
}
}
return true;
}
}