首页 > 试题广场 >

判断是不是完全二叉树

[编程题]判断是不是完全二叉树
  • 热度指数:63600 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给定一个二叉树,确定他是否是一个完全二叉树。

完全二叉树的定义:若二叉树的深度为 h,除第 h 层外,其它各层的结点数都达到最大个数,第 h 层所有的叶子结点都连续集中在最左边,这就是完全二叉树。(第 h 层可能包含 [1~2h] 个节点)

数据范围:节点数满足
样例图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

说明:本题目包含复杂数据结构TreeNode,点此查看相关信息
/**
 * struct TreeNode {
 *	int val;
 *	struct TreeNode *left;
 *	struct TreeNode *right;
 *	TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 * };
 */
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param root TreeNode类 
     * @return bool布尔型
     */
    bool isCompleteTree(TreeNode* root) {
        int maxLayer = 0;
        std::map<int,vector<TreeNode*>> table;
        std::function<void(TreeNode*,int)> dfs = [&](TreeNode* p, int layer) ->void {
            table[layer].push_back(p);
            maxLayer = max(maxLayer, layer);
            if(p->left){
                dfs(p->left, layer + 1);
            }
            if(p->right){
                dfs(p->right, layer + 1);
            }
        };
        dfs(root,0);
        if(maxLayer == 0){
            return true;
        }
        int num = table[maxLayer - 1].size();
        if(num != pow(2,maxLayer-1)) {
            return false;
        }
        else{
            bool flag = true;
            for(auto& node : table[maxLayer-1]){
                if(!flag && (node->right||node->left)){
                    return false;
                }

                if(!node->right||!node->left) {
                    flag = false;
                    if(node->left == nullptr && node->right)
                    {
                        return false;
                    }
                }
            }
   
        }

        return true;
    }
};

发表于 2022-07-10 17:39:14 回复(0)

基于层次遍历判断是否为完全二叉树

package main

import . "nc_tools"

/*
 * type TreeNode struct {
 *   Val int
 *   Left *TreeNode
 *   Right *TreeNode
 * }
 */

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 *
 * @param root TreeNode类
 * @return bool布尔型
 */
func isCompleteTree(root *TreeNode) bool {
	if root == nil {
		return true
	}
    
    notComplete := false
    queue := []*TreeNode{root}
    for len(queue) > 0 {
        tempQueue := []*TreeNode{}
        for _, node := range queue {
            if node == nil {
                notComplete = true
                continue
            }
            if notComplete {
                return false // 第二次出现空节点
            }
            
            tempQueue = append(tempQueue, node.Left)
            tempQueue = append(tempQueue, node.Right)
        }
        queue = tempQueue
    }
    
    return true
}


发表于 2022-05-19 23:00:33 回复(0)
public boolean isCompleteTree (TreeNode root) {
        // write code here
        if(root == null) return true;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        TreeNode cur;
        boolean flag = false;
        while(!queue.isEmpty()){
            cur = queue.poll();
            if(cur == null){
                flag = true;
                continue;
            }
            if(flag) return false;
            queue.offer(cur.left);
            queue.offer(cur.right);
        }
        return true;
    }

发表于 2021-12-03 19:15:35 回复(1)
class Solution {
  public:
    int y = 1e9;
    int cnt = 0;
    void dfs(TreeNode* root, int x) {
        if (!root) {
            y = min(y, x);
            return;
        }
        ++cnt;
        dfs(root->left, x * 2);
        dfs(root->right, x * 2 + 1);
    }
    bool isCompleteTree(TreeNode* root) {
        dfs(root, 1);
        return y == cnt + 1;
    }
};

发表于 2022-04-14 20:13:58 回复(0)
bool isCompleteTree(struct TreeNode* root ) {
    struct TreeNode **queue=(struct TreeNode*)malloc(sizeof(struct TreeNode*)*100);
    int f=-1,r=-1;
    queue[++r]=root;
    int flag=0;
    while(r!=f){
        struct TreeNode *k=queue[++f];
        if(k!=NULL){
            if(flag) return 0;
            queue[++r]=k->left;
            queue[++r]=k->right;
        }
        else{
            flag=1;
        }        
    }
    return flag;
}
采用层次遍历  送给考研的大家 C版本

发表于 2022-08-15 21:42:56 回复(2)
BFS求解,有两个判断准则:
  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
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        boolean flag = false;
        while(!queue.isEmpty()){
            TreeNode node = queue.poll();
            // 有右孩子没有左孩子
            if(node.right != null && node.left == null) return false;
            // 遇到了左右孩子不双全的节点后,遇到了非叶子节点
            if(flag && (node.left != null || node.right != null)) return false;
            // 遇到左右孩子不双全的节点
            if((node.left != null && node.right == null) || (node.left == null && node.right == null)) flag = true;
            if(node.left != null) queue.offer(node.left);
            if(node.right != null) queue.offer(node.right);
        }
        return true;
    }
}

编辑于 2022-02-26 21:08:48 回复(4)
/**
 * struct TreeNode {
 *	int val;
 *	struct TreeNode *left;
 *	struct TreeNode *right;
 *	TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 * };
 */
class Solution {
public:
  bool isCompleteTree(TreeNode* root) {
  // 层序遍历 利用完全二叉树条件
    if (root == nullptr) return true;
    queue<TreeNode* > que;
    que.push(root);
    while (!que.empty()) {
      TreeNode* cur = que.front();
      que.pop();
      if (cur != nullptr) {
        // 完全二叉树条件1:有右无左 返回false
        if (cur -> left == nullptr && cur -> right != nullptr)
          return false;
        // cur的左右子节点入队
        que.push(cur -> left);
        que.push(cur -> right);
      } else 
        // 遇到空节点 循环终止
        break;
    }
    // 二次while判断不满足上述条件1(左无右有)后仍有不满足:
    // 条件2 完全二叉树叶子节点须从左至右依次排列
    // 队列还为空 如果头结点非空 则返回false 空则出队
    while (!que.empty()) {
      if (que.front() != nullptr) return false;
      else que.pop(); 
    }
    return true;
  }
};

发表于 2022-08-09 10:55:16 回复(0)
判断是不是完全二叉树

区别是:完全二叉树在层序遍历中最后出现null后,一直是null。而非完全二叉树则是在层序遍历中出现null后,后面还出现非null节点。

所以直接层序遍历,这个特殊,由于需要判断null,所以要加null到queue里。
当poll出来为null时,需要continue。如果是完全二叉树,则一直continue到结束。
如果是非完全二叉树,则会poll出来非null,这里最好记录一个boolean变量,表示是否到达节点尾,从而当null后面出现非null节点时直接返回false

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
        //层序遍历,在队列里加null。完全二叉树当poll出null时,后面应该都是null
        //非完全二叉树,poll出一个null后,后面还有非null元素
        
        //层序遍历,需要加null进去判断(通常不用加null)
        if(root == null) return true;
        LinkedList<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        boolean isLast = false;
        while(!queue.isEmpty()){
            TreeNode t = queue.poll();
            //如果是完全二叉树,t应该一直为null,直到结束
            if(t == null){
                isLast = true;
                continue;
            }
            //非完全二叉树,出现null后又出现非null元素
            if(isLast){
                return false;
            }
            //加入的是t的左节点和右节点
            queue.offer(t.left);
            queue.offer(t.right);
        }
        return true;
    } 
}


发表于 2022-07-25 16:53:21 回复(3)
采用队列按层遍历
1. 如果poll出的结点不为null,就将左右都放进去。
2. 如果poll出的节点为null,判断队列中是否存在非null元素。
如果一个节点存在右节点,不存在左节点时,一定不是完全二叉树,直接返回即可。
public boolean isCompleteTree (TreeNode root) {
        // write code here
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            TreeNode node = queue.poll();
            if (node != null) {
                if (node.right != null && node.left == null) return false;
                queue.offer(node.left);
                queue.offer(node.right);
            } else {
                break;
            }
        }
        while (!queue.isEmpty()) {
            if (queue.poll() != null) {
                return false;
            }
        }
        return true;
    }


发表于 2022-04-03 10:15:06 回复(0)
/**
 * struct TreeNode {
 *	int val;
 *	struct TreeNode *left;
 *	struct TreeNode *right;
 *	TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 * };
 */
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param root TreeNode类 
     * @return bool布尔型
     */
    bool isCompleteTree(TreeNode* root) {
        // write code here
        if(!root)return 1;
        queue<TreeNode*> q;
        q.push(root);
        while(!q.empty()) {//空指针也可以压入
            int sz = q.size();
            while(sz--) {
                auto cur = q.front();
                if(!cur){//域间空指针后看后没是不是全是空指针
                    while(!q.empty() && !q.front())
                        q.pop();
                    if(q.empty())return 1;//全是空
                    else return 0;//不全是空
                }
                q.pop();
                // 空指针也压进去
                q.push(cur->left);
                q.push(cur->right);

            }
            }
        return 1;
        
    }
};

发表于 2022-03-16 11:15:42 回复(0)
public class Solution {
    int ans = 0;
    int helper(TreeNode root, int idx){
        if(root == null) return 0;
        ans = Math.max(ans, idx);
        return 1 + helper(root.left, idx * 2) + helper(root.right, idx * 2 + 1);
    }
    public boolean isCompleteTree (TreeNode root) {
        return helper(root, 1) == ans;
    }
}

发表于 2022-02-23 20:07:44 回复(2)
public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param root TreeNode类
     * @return bool布尔型
     */
    public boolean isCompleteTree (TreeNode root) {
        // write code here
        if (root == null)
            return true;
        LinkedList<TreeNode> queue = new LinkedList<>();
        boolean leaf = false;
        queue.add(root);
        while (!queue.isEmpty()) {
            root = queue.poll();
            TreeNode r = root.right;
            TreeNode l = root.left;
            if ((l == null && r != null) || (leaf && (l != null || r != null))) {
                return false;
            }
            if (l != null) {
                queue.add(l);
            }
            if (r != null) {
                queue.add(r);
            }
            if (l == null || r == null) {
                leaf = true;
            }
        }
        return true;
    }
}
编辑于 2024-04-08 15:51:54 回复(0)
使用层序遍历二叉树,然后看看是左子树是否为空,如果是空,通过判断遍历到右子树的时候直接返回false。
    public boolean isCompleteTree (TreeNode root) {
        // write code here
        if(root == null) return true;
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.add(root);
        boolean isHasLeft = true;
        while(!queue.isEmpty()) {
            TreeNode poll = queue.poll();
            if(poll == null) isHasLeft = false;
            else{
                if(isHasLeft == false) return isHasLeft;
                queue.add(poll.left);
                queue.add(poll.right);
            }
        }
        return true;
    }


发表于 2023-11-12 11:49:00 回复(0)
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param root TreeNode类 
# @return bool布尔型
#
class Solution:
    def isCompleteTree(self , root: TreeNode) -> bool:
        # write code here
        if root is None:
            return True
        
        queue = [root]
        is_missing_child = False
        
        while len(queue) > 0:
            node = queue.pop(0)
            
            # 针对缺失节点的情况进行判断
            if node is None:
                is_missing_child = True
                continue
            elif is_missing_child:
                return False
            
            # 将左右子节点加入队列
            queue.append(node.left)
            queue.append(node.right)
        
        return True

发表于 2023-10-16 17:23:01 回复(0)
/**
 * struct TreeNode {
 *  int val;
 *  struct TreeNode *left;
 *  struct TreeNode *right;
 *  TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 * };
 */
#include <queue>
#include <vector>
class Solution {
  public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param root TreeNode类
     * @return bool布尔型
     */
    bool isCompleteTree(TreeNode* root) {
        if (root == nullptr)
            return true;
        queue<TreeNode*> s;
        vector<int> v;
        int size = 0;
        s.push(root); 
        while (!s.empty()) {
            TreeNode* now = s.front();
            s.pop();
            if(now!=nullptr){
                v.push_back(now->val);
                s.push(now->left);
                s.push(now->right);
            }
            else{
                v.push_back(-1);
            }
            size++;
        }
        bool flag =true;
        for(int i=size-1;i>0;i--){
            if(v[i]!=-1){
                flag=false;
            }
            if(v[i]==-1&&!flag)
            return false;
        }
        return true;
    }
};

发表于 2023-09-16 20:21:47 回复(0)
//这道题的测试用例存在缺陷,有些错误的思路也是可以测试通过的,下面的代码中有一段被注释掉的错误递归思路但是却可以通过测试,没注释掉的是正确的思路
/**
 * struct TreeNode {
 *  int val;
 *  struct TreeNode *left;
 *  struct TreeNode *right;
 *  TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 * };
 */
class Solution {
  public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param root TreeNode类
     * @return bool布尔型
     */
    bool isCompleteTree(TreeNode* root) {
        // write code here
        // //思路:递归处理,分别进入到左右子树,左右子树都存在保证子树根节点孩子一定是顺序排列的,不断递归下去进行判断,此种方法可以通过测试但是实际是不正确的
        // if(!root||!root->left&&!root->right)return true;
        // if(root->right&&!root->left)return false;
        // TreeNode*L=root->left;
        // TreeNode*R=root->right;
        // if(L&&R){
        // if(L->right==nullptr||L->left==nullptr){
        //     if(R->right||R->left)return false;
        // }
        // if(R->left==nullptr&&R->right)return false;}
        // if(L&&!R){if(L->right||L->left)return false;}
        // isCompleteTree(L);
        // isCompleteTree(R);
        // return true;
        //正确的思路:利用队列进行层序遍历,遍历每一层时遇到空指针检查后面是否全为空指针,如果有不为空指针的话就不是完全二叉树
        if (!root)return true;
        queue<TreeNode*> q;
        q.push(root);
        while (!q.empty()) { //空指针也可以压入
            int sz = q.size();
            while (sz--) {
                auto cur = q.front();
                if (!cur) { //域间空指针后看后没是不是全是空指针
                    while (!q.empty() && !q.front())
                        q.pop();
                    if (q.empty())return true; //全是空
                    else return false;//不全是空
                }
                q.pop();
                // 空指针也压进去
                q.push(cur->left);
                q.push(cur->right);

            }
        }
        return true;

    }
};

发表于 2023-08-23 19:13:11 回复(0)
思路:完全二叉树需要满足以下几个条件:
当该行不完整时,需确保:
1.该行中每个节点都没有子节点
2.不能出现有左节点没有右节点的情况
3.若该行中已有空节点则后续不能存在任何节点
然后根据这三条使用广度优先遍历,并按顺序判断即可。
代码:
func isCompleteTree(root *TreeNode) bool {
	var queue = list.New()
	var count = 0
	queue.PushBack(root)
	for queue.Len() != 0 {
		size := queue.Len()
		count++
		mayCount := int(math.Pow(float64(2), float64(count-1)))
		var isComplete = true
		for i := 0; i < size; i++ {
			node := queue.Front().Value.(*TreeNode)
			queue.Remove(queue.Front())

			if size != mayCount && (node.Left != nil || node.Right != nil) {
				return false
			}
			if node.Right != nil && node.Left == nil {
				return false
			}
			if (node.Left != nil || node.Right != nil) && isComplete == false {
				return false
			}
			if node.Left == nil || node.Right == nil {
				isComplete = false
			}

			if node.Left != nil {
				queue.PushBack(node.Left)
			}
			if node.Right != nil {
				queue.PushBack(node.Right)
			}
		}
	}
	return true
	// write code here
}


发表于 2022-11-15 17:32:42 回复(0)
BFS广度优先求解
public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param root TreeNode类 
     * @return bool布尔型
     */
    public boolean isCompleteTree (TreeNode root) {
       // 如果根为null,就返回true
        if(root == null){
            return true;
        }
        /*
         * 判断不是完全二叉树,有3种情况:
         *      1. 左子节点为空,右子节点不为空
         *      2. 当左子节点不为空,右子节点为空的时候,后面继续迭代当前层时,只要发现还有节点 它就不是完全二叉树
         *      2. 当左子节点不为空,右子节点为空的时候,后面继续迭代下一层时,只要发现还有下一层有节点,它就不是完全二叉树
         */

        // 定义一个链表,用于保存每一层的节点
        LinkedList<TreeNode> linked = new LinkedList<>();

        linked.add(root);  // 先添加根节点

        boolean flag = false; // 定义一个状态码,当出现右子节点为null时,就设置为true

        int size; // 保存循环中每一次链表的长度

        TreeNode treeNode; // 保存每一次取出的链表头节点

        // 链表不为空 循环继续
        while (!linked.isEmpty()){
            // 获取链表长度
            size = linked.size();

            // 根据size 进行循环 依次取出链表头节点
            for (int i = 0; i < size; i++) {
                // 取出头节点
                treeNode = linked.removeFirst();

                // 只要左子节点为空,右子节点不为空  直接返回false
                if(treeNode.left == null && treeNode.right != null) return false;

                // 能执行到这里,只有以下两种情况
                // 1.treeNode.left!=null   (right可能 null || !null)
                // 2.treeNode.left ==null  treeNode.right==null

                // 只要左子节点有值 就添加链表
                if(treeNode.left !=null){
                    // 如果flag为真,表示在这之前的层级或者当前层级中 已经出现了right为空的情况,
                    // 既然已经出现过right为空的情况  那么此if代码块还能进入,已经不是完全二叉树了。就返回false
                    // 首次执行到这,flag一定为false
                    if(flag) return false;
                    // 链表添加节点
                    linked.add(treeNode.left);
                }
                // right!=null 链表添加节点
                if(treeNode.right != null)linked.add(treeNode.right);
                // right为空,flag设置为true
                else flag = true;

            }
        }
        // 循环结束,表示该树符合完全二叉树,返回true
        return true;
    }
}


发表于 2022-11-06 12:26:53 回复(0)
/**
 * struct TreeNode {
 *	int val;
 *	struct TreeNode *left;
 *	struct TreeNode *right;
 *	TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 * };
 */
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param root TreeNode类 
     * @return bool布尔型
     */
    bool isCompleteTree(TreeNode* root) {
        // 时间复杂度O(N),空间复杂度O(N)
        if (root == nullptr) return true;
        queue<TreeNode*> que;
        que.push(root);
        bool flag = false;
        while (!que.empty()) {
            TreeNode* node = que.front();
            que.pop();
            if (node->left) {
                if (flag) return false;
                que.push(node->left);
            } else flag = true;
            if (node->right) {
                if (flag) return false;
                que.push(node->right);
            } else flag = true;
        }
        return true;
    }
};

发表于 2022-10-09 17:59:10 回复(0)
//使用类似堆的思想,获取最大位置数,若最大数前有nulptr,则false;
class Solution {
  public:
    void getMaxNum(TreeNode* rootint& maxnint pos) {
        if(!root){
            return;
        }
        maxn = max(maxn, pos);                 //获取最大非空位置
        getMaxNum(root->left, maxn, pos * 2);  //从1开始数
        getMaxNum(root->right, maxn, pos * 2 + 1);
    }

    bool getIsCompleteTree(TreeNode* rootint posint maxn){
        if(!root) {
            if(pos < maxn) {     //前面是否有空
                return false;
            }
            else {
                return true;
            }
        }
        return getIsCompleteTree(root->left, pos * 2, maxn) & getIsCompleteTree(root->right, pos * 2 + 1, maxn);
    }
    bool isCompleteTree(TreeNode* root) {
        // write code here
        if(!root) {
            return true;
        }
        int maxn = 0, pos = 1;
        getMaxNum(root, maxn, pos);
        cout << "maxn = " << maxn << endl;
        return getIsCompleteTree(root, pos, maxn);
    }
};

发表于 2022-10-06 20:49:44 回复(0)

问题信息

难度:
108条回答 3495浏览

热门推荐

通过挑战的用户

查看代码