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

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

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

    1
   / \
  2   3
 / \  /
4  5 6

输出: 6

思路:
和广大人民群众一样,我上来也是直接写出了这样一段代码(code1),然后毫无疑问的超时了QAQ…
其实我们发现code1所示代码,对于每个节点都要搜索一下左右子树才能确定最后的高度。但是这是一个完全二叉树,意味着其实对于一些节点没有必要搜索就能确定最后的高度。
超时code 1:

class Solution {
public:
    int countNodes(TreeNode* root) {
        if(root==NULL) return 0;
        int l=countNodes(root->left);
        int r=countNodes(root->right);
        return l+r+1;
    }
};

法一:
首先从根节点求出左子树和右子树的高度,如果左子树和右子树同样高,那么左子树一定是满二叉树,这时候总的叶子个数为:左子树的叶子个数+根节点+剩下的还未遍历的右子树叶子个数(图1左侧),而左子树叶子个数+根节点总数为: 2 d 2^d 2d,其中d为左子树的高度,这样左子树那部分的节点就没有必要继续搜索了;
如果左子树比右子树高,说明右子树一定是满二叉树,这时候总的叶子个数为:右子树的叶子个数+根节点+剩下的还未遍历的左子树叶子个数,这样右子树那部分节点就没有必要继续搜索了(见图1右侧)。
总感觉讲复杂了qwq…代码见code2
在这里插入图片描述
图1 完全二叉树搜索的两种情况
code 2:

class Solution {
public:
    int countNodes(TreeNode* root) {
        if(root==NULL) return 0;
        int L=getDepth(root->left);
        int R=getDepth(root->right);
        
        if(L==R) return (1<<L)+countNodes(root->right);//两边子树高度相同,左子树+还未遍历的右子树部分,右移运算需要加括号
        if(L>R) return (1<<R)+countNodes(root->left);//左边子树高度更高,说明右边子树为满二叉树,所以右子树+还没便利的左子树部分
    }
    int getDepth(TreeNode *root){
        if(root==NULL) return 0;
        int L=getDepth(root->left);
        return L+1;
    }
};

法二:
有点记忆化搜索的味道,将之前出现过的节点先标记成一个最小值,下次递归返回时减少搜索量。

class Solution {
public:
    int countNodes(TreeNode* root) {
        if(root==NULL) return 0;
        if(root->val==INT_MIN) return 0;
        
        root->val=INT_MIN;
        int l=countNodes(root->left);
        int r=countNodes(root->right);
        return l+r+1;
    }
};

思路一参考自:
https://leetcode-cn.com/problems/count-complete-tree-nodes/comments/

posted @ 2018-12-07 21:48  xzhws  阅读(45)  评论(0编辑  收藏  举报