zoukankan      html  css  js  c++  java
  • 222. 完全二叉树的节点个数

    222. 完全二叉树的节点个数

    题目链接:222. 完全二叉树的节点个数(中等)

    题目描述

    给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。

    完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。

    示例 1:

    输入:root = [1,2,3,4,5,6]
    输出:6

    示例 2:

    输入:root = []
    输出:0

    示例 3:

    输入:root = [1]
    输出:1

    提示:

    • 树中节点的数目范围是[0, 5 * 104]

    • 0 <= Node.val <= 5 * 104

    • 题目数据保证输入的树是 完全二叉树

    进阶:遍历树来统计节点是一种时间复杂度为 O(n) 的简单解决方案。你可以设计一个更快的算法吗?

    题解

    思路:不考虑”进阶“,完全二叉树就是一棵二叉树,求节点的个数和遍历节点类似。但由于完全二叉树的特殊性。由下图我们可以发现:如果左子树的深度等于右子树的深度,则左子树为满二叉树;如果左子树的深度大于右子树的深度,则右子树为满二叉树。

    代码(C++):

    struct TreeNode {
        int val;
        TreeNode* left;
        TreeNode* right;
        TreeNode(int value) : val(value), left(nullptr), right(nullptr) {}
    };
    ​
    ​
    class Solution1 {
    public:
        //按照一般的二叉树来求,有递归法和迭代法
        //方法一:后序遍历(递归法)
        int countNodes(TreeNode* root) {
            if (root == nullptr) return 0;
            int leftNums = countNodes(root->left);
            int rightNums = countNodes(root->right);
            int nums =leftNums + rightNums + 1;
            return nums;
        }
    };
    ​
    class Solution2 {
    public:
        //按照一般的二叉树来求,有递归法和迭代法
        //方法二:层次遍历(迭代法)
        int countNodes(TreeNode* root) {
            queue<TreeNode*> que;
            if (root != nullptr) que.push(root);
            int nums = 0;
            while (!que.empty()) {
               TreeNode* node = que.front();
               que.pop();
               nums++;
               if (node->left) que.push(node->left);
               if (node->right) que.push(node->right);
            }
            return nums;
        }
    };
    ​
    class Solution3 {
    public:
        //完全二叉树是特殊的二叉树
        //方法三:
        int getDepth (TreeNode* node) {
            int depth = 0;
            while (node) {
                depth++;
                node = node->left;
            }
            return depth;
        }
        int countNodes(TreeNode* root) {
            if (root == nullptr) return 0;
            // 以根节点分成左子树和右子树,分别求他们的深度
            int leftDepth = getDepth(root->left);
            int rightDepth = getDepth(root->right);
    ​
            if (leftDepth == rightDepth) {
                return countNodes(root->right) + (pow(2,leftDepth) - 1) + 1;
            } else {
                return (pow(2,rightDepth) - 1 ) + countNodes(root->left) + 1;
            }
        }
    };

    代码(JavaScript):

    //构造函数
    function TreeNode(val, left, right) {
        this.val = (val === undefined ? 0 : val);
        this.left = (left === undefined ? null : left);
        this.right = (right == undefined ? null : right);
    }
    ​
    var root = new TreeNode();
    ​
    //方法一:递归法(后序遍历)
    var countNodes = function(root) {
        if (root === null) return 0;
        var leftNums = countNodes(root.left);
        var rightNums = countNodes(root.right);
        return rightNums + leftNums + 1;
    };
    ​
    //方法二:迭代法(层次遍历)
    var countNodes1 = function(root) {
        var que = new Array();
        if (root != null) que.push(root);
        var Nums = 0;
        while (que.length != 0) {
            var node = que.shift();
            Nums++;
            if (node.left) que.push(node.left);
            if (node.right) que.push(node.right);
        }
        return Nums;
    };
    ​
    ​
    //方法三:利用二叉树的性质
    function getDepth(node) {
        var depth = 0;
        while (node) {
            depth++;
            node = node.left;
        }
        return depth;
    }
    ​
    var countNodes2 = function(root) {
        if (root === null) return 0;
        var leftDepth = getDepth(root.left);
        var rightDepth = getDepth(root.right);
        if (leftDepth === rightDepth) {
            return countNodes(root.right) + (Math.pow(2, leftDepth) - 1) + 1;
        } else {
            return (Math.pow(2, rightDepth) - 1) + countNodes(root.left) + 1;
        }
    };

    分析:

    普通二叉树的方法(方法一,方法二)

    • 时间复杂度:O(N),N是树的节点个数

    • 空间复杂度:方法一(O(logN)),递归中栈的开销;方法二(O(N)),迭代中队列的开销;

    满二叉树(方法三)

    • 时间复杂度:O(logN * logN)

    • 空间复杂度:O(logN )

  • 相关阅读:
    java-mybaits-00503-延迟加载
    java-mybaits-00502-案例-映射分析-一对一、一对多、多对多
    java-mybaits-00501-案例-映射分析-订单商品数据模型
    java-mybaits-00402-Mapper-动态sql-if、where、foreach、sql片段
    数据结构与算法实验题7.1 M 商人的求救
    HDOJ 1075
    HDOJ 1856
    HDOJ 3790
    HDOJ 1869
    HDOJ 1870
  • 原文地址:https://www.cnblogs.com/wltree/p/15634974.html
Copyright © 2011-2022 走看看