判断二叉树是否为满二叉树

判断,二叉树,是否 · 浏览次数 : 477

小编点评

**方法一:使用公式** ```java public static boolean isFull1(Node head) { if (head == null) { return true; } Info1 all = process1(head); return (1 << all.height) - 1 == all.nodes; } ``` **方法二:使用数据结构** ```java public static boolean isFull2(Node head) { if (head == null) { return true; } return process2(head).isFull; } ``` **方法1的优点:** * 使用公式计算树的高度和结点数量,简便易懂。 * 运行时间较短,适合大量测试。 **方法2的优点:** * 使用数据结构维护树的信息,可以避免重复计算。 * 运行时间更快,适用于判断树是否为满二叉树的特殊情况。 **方法比较:** | 特征 | 方法一 | 方法二 | |---|---|---| | 计算方法 | 公式 | 数据结构 | | 运行时间 | 较短 | 较长 | | 适用性 | 适用于大多数情况 | 适用于判断特殊情况的树 | | 代码复杂性 | 较低 | 较高 | | 维护树信息 | 无 | 有 |

正文

判断二叉树是否为满二叉树

作者:Grey

原文地址:

博客园:判断二叉树是否为满二叉树

CSDN:判断二叉树是否为满二叉树

满二叉树定义

一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K,且结点总数是(2^k) -1 ,则它就是满二叉树。

方法1

使用公式,求二叉树的层数 k, 结点数 n,如果满足(2^k) -1 = n,则为满二叉树。

定义数据结构

    public static class Info1 {
        public int height;
        public int nodes;

        public Info1(int h, int n) {
            height = h;
            nodes = n;
        }
    }

其中height表示二叉树的层数,nodes表示二叉树的结点个数。

定义递归函数

Info1 process1(Node head)

递归含义是:head 为头的二叉树的层数和点数都是多少,接下来就是 base case

即:head == null的时候,此时,height == 0nodes == 0

        if (head == null) {
            return new Info1(0, 0);
        }

接下来是普遍情况

// 去左树上收集信息
Info1 leftInfo = process1(head.left);
// 去右树上收集信息
Info1 rightInfo = process1(head.right);
// 整合成 head 自己的信息
int height = Math.max(leftInfo.height, rightInfo.height) + 1;
int nodes = leftInfo.nodes + rightInfo.nodes + 1;
return new Info1(height, nodes);

方法2

定义如下数据结构

    public static class Info2 {
        public boolean isFull;
        public int height;

        public Info2(boolean f, int h) {
            isFull = f;
            height = h;
        }
    }

其中isFull表示是否为满二叉树,height表示二叉树的高度。

定义了这个数据结构后,可以梳理可能性,如果以 head 为头的树要符合满二叉树。则需要同时满足下面三种情况

情况1:左树是满二叉树

情况2:右树是满二叉树;

情况3:左右树的高度一样。

定义递归函数

Info2 process2(Node head)

递归含义就是返回以head为头的二叉树Info2结构信息。

base case是

        if (h == null) {
            return new Info2(true, 0);
        }

h == null默认是满二叉树,结点个数为0。

接下来是普遍情况,即去左右子树收集相关信息,整合成以h为头二叉树的信息。

    // 去左子树收集相关信息
    Info2 leftInfo = process2(h.left);
    // 去右子树收集相关信息
    Info2 rightInfo = process2(h.right);
    // 整合成 h 自己的新
    boolean isFull = leftInfo.isFull && rightInfo.isFull && leftInfo.height == rightInfo.height;
    int height = Math.max(leftInfo.height, rightInfo.height) + 1;
    return new Info2(isFull, height);

方法1 和 方法2 的时间复杂度都是O(n),即经过一次后序遍历的时间复杂度。

两种解法的完整代码(含测试代码)如下

public class Code_IsFull {
    public static class Node {
        public int value;
        public Node left;
        public Node right;

        public Node(int data) {
            this.value = data;
        }
    }

    // 第一种方法
    // 收集整棵树的高度h,和节点数n
    // 只有满二叉树满足 : 2 ^ h - 1 == n
    public static boolean isFull1(Node head) {
        if (head == null) {
            return true;
        }
        Info1 all = process1(head);
        return (1 << all.height) - 1 == all.nodes;
    }

    public static class Info1 {
        public int height;
        public int nodes;

        public Info1(int h, int n) {
            height = h;
            nodes = n;
        }
    }

    public static Info1 process1(Node head) {
        if (head == null) {
            return new Info1(0, 0);
        }
        Info1 leftInfo = process1(head.left);
        Info1 rightInfo = process1(head.right);
        int height = Math.max(leftInfo.height, rightInfo.height) + 1;
        int nodes = leftInfo.nodes + rightInfo.nodes + 1;
        return new Info1(height, nodes);
    }

    // 第二种方法
    // 收集子树是否是满二叉树
    // 收集子树的高度
    // 左树满 && 右树满 && 左右树高度一样 -> 整棵树是满的
    public static boolean isFull2(Node head) {
        if (head == null) {
            return true;
        }
        return process2(head).isFull;
    }

    public static class Info2 {
        public boolean isFull;
        public int height;

        public Info2(boolean f, int h) {
            isFull = f;
            height = h;
        }
    }

    public static Info2 process2(Node h) {
        if (h == null) {
            return new Info2(true, 0);
        }
        Info2 leftInfo = process2(h.left);
        Info2 rightInfo = process2(h.right);
        boolean isFull = leftInfo.isFull && rightInfo.isFull && leftInfo.height == rightInfo.height;
        int height = Math.max(leftInfo.height, rightInfo.height) + 1;
        return new Info2(isFull, height);
    }

    // for test
    public static Node generateRandomBST(int maxLevel, int maxValue) {
        return generate(1, maxLevel, maxValue);
    }

    // for test
    public static Node generate(int level, int maxLevel, int maxValue) {
        if (level > maxLevel || Math.random() < 0.5) {
            return null;
        }
        Node head = new Node((int) (Math.random() * maxValue));
        head.left = generate(level + 1, maxLevel, maxValue);
        head.right = generate(level + 1, maxLevel, maxValue);
        return head;
    }

    public static void main(String[] args) {
        int maxLevel = 5;
        int maxValue = 100;
        int testTimes = 1000000;
        System.out.println("测试开始");
        for (int i = 0; i < testTimes; i++) {
            Node head = generateRandomBST(maxLevel, maxValue);
            if (isFull1(head) != isFull2(head)) {
                System.out.println("出错了!");
            }
        }
        System.out.println("测试结束");
    }
}

更多

算法和数据结构笔记

与判断二叉树是否为满二叉树相似的内容:

判断二叉树是否为满二叉树

判断二叉树是否为满二叉树 作者:Grey 原文地址: 博客园:判断二叉树是否为满二叉树 CSDN:判断二叉树是否为满二叉树 满二叉树定义 一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K,且结点总数是(2^k) -1 ,则它就是满二叉树。 方

leetcode 平衡二叉树

给定一个二叉树,判断它是否是高度平衡的二叉树。 本题中,一棵高度平衡二叉树定义为: 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。 示例 1: 输入:root = [3,9,20,null,null,15,7] 输出:true 示例 2: 输入:root = [1,2,2,3,3,

[转帖]总结:shell中的if条件判断

一、if 的基本语法 if [ command ];then xxxelif [ command ];then xxxelse xxxfi 二、常见的一些写法案例 1、if [ "x${var}" = "x" ] 其实就是判断${var}是否为空的意思 2、if [ X"$?" == X"0" ]

Inno setup 脚本判断 Microsoft Visual C++ Redistributable 不同版本区别

有个需要是需要在安装包安装初始化时安装 Microsoft Visual c++ 2013 Redistributable 也就是判断软件安装前需不需要运行 `vcredist_x64.exe` 和 `VC_redist.x64.exe` 这两个程序 第一反应就是可以通过注册表判断是否已经安装过环境

测试type和isinstance两个函数,那个速度更加的快

一、解决方案 通过装饰器实现二、相关知识点 isinstance()函数 1. isinstance()函数是python中的一个内置函数,作用:判断一个函数是否是一个已知类型,类似type()。 2. 语法:isinstance ( object , classinfo ) 参数: object:

软件设计模式系列之二十二——状态模式

状态模式是一种行为型设计模式,它允许对象在内部状态发生改变时改变其行为,使得对象的行为看起来像是改变了其类。状态模式将对象的状态抽象成一个独立的类,让对象在不同状态下具有不同的行为,而且可以在运行时切换状态。这种方式使得状态的管理更加清晰,避免了大量的条件判断语句,提高了代码的可维护性和可扩展性。

Spring源码:Bean的生命周期(二)

FactoryBean 和 BeanFactory 是两个不同的概念。前者是一个接口,我们可以在实现该接口时通过调用 getObject 方法来返回实例,同时 FactoryBean 本身也是一个实例。后者是 Spring 容器的工厂,通过其中的 bean 定义 Map 一个一个地实例化我们通过注解等方式注入进去的 bean 工厂。在判断 FactoryBean 时,如果当前 BeanFactor

[转帖]Shell if 条件判断

Shell 语言中的if条件 一、if的基本语法: if [ command ];then 符合该条件执行的语句 elif [ command ];then 符合该条件执行的语句 else 符合该条件执行的语句 fi 二、文件/文件夹(目录)判断 [ -b FILE ] 如果 FILE 存在且是一个

设计模式学习(二)工厂模式——工厂方法模式+注册表

目录工厂方法模式的瑕疵注册表 工厂方法模式的瑕疵 在前一篇笔记中我们介绍了工厂方法模式,示例的类图如下: 考虑一种情况:现在要在程序运行时,根据外部资源,动态的实例化对象。也就是说在编译期我们无法知道要实例化的对象的类型。因此在实例化的过程中,就需要加以判断。 例如,在我的例子中,要根据连接到主机的

【FAQ】关于无法判断和区分用户与地图交互手势类型的解决办法

### 一. 问题描述 当用户通过缩放手势、平移手势、倾斜手势和旋转手势与地图交互,控制地图移动改变其可见区域时,华为地图SDK没有提供直接获取用户手势类型的API。 ### 二. 解决方案 1. 华为地图SDK的地图相机有提供CameraPosition类,此类包括所有相机位置参数,如位置、方位、