222. Count Complete Tree Nodes

Given a complete binary tree, count the number of nodes.

Definition of a complete binary tree from Wikipedia:
In a complete binary tree every level, except possibly the last, is completely filled, and all nodes in the last level are as far left as possible. It can have between 1 and 2h nodes inclusive at the last level h.
题目要求:给你一个完全二叉树,求总共的节点数。
原始方法:

int countNodes(TreeNode* root) {
   if(!root) return 0;
   return countNodes(root->left)+countNodes(root->right)+1;
  }

这里的算法复杂度是: O(n)
因为这里的二叉树的特点是完全二叉树,因此可以根据这个特点进行优化。

/*
eg1:有如下的一颗完全二叉树(左孩子满)
                              o
                            /   \
                           o     o  
                          / \   / \
                         o  o  o   o
                        / \/ \/
                       o  oo oo 
   如果完全二叉树的最后一行是满的,那么它左孩子和右孩子的高度应该是一样的。这里先求得
   root根节点的高度h,如果右孩子的高度恰好为h-1,那么说明它的左孩子必定是满的(最后一行部空)。此时,可以确定它的左孩子的总节点数是2^h-1个,加上一个根节点,目前计数为2^h个。如下所示:
                               x
                            /    \
                           x      o <- 新的根节点 
                          / \    / \
                         x   x  o   o
                        / \ / \/
                       x  x x xo     
                   (x是已经计数的,o是未计数的)
  此时,只再需要对它的右孩子进行计数即可。
  以上讨论的是第一种情况,左孩子满的情况,还有可能左孩子不是满的,如下图所示。此时,右孩子必定也是一颗满的完全二叉树,但此时它的高度是h-2,故此时右孩子的节点总数为2^(h-1)-1, 此时加上根节点总数为2^(h-1)个。再对左孩子进行计数。
 eg2:有如下的一颗完全二叉树(左孩子不满)
                              o
                            /   \
                           o     o  
                          / \   / \
                         o  o  o   o
                        / \/ 
                       o  oo 

对右孩子进行计完树之后,再对左孩子计数。
                              x
                            /   \
            新的根节点 ->   o     x  
                          / \   / \
                         o  o  x   x
                        / \/ 
                       o  oo    
                    (x是已经计数的,o是未计数的)           
 */
 int countNodes(TreeNode* root) {
    // int h=height(root);
    // return h<0?0:height(root->right)==h-1?(1<<h)+countNodes(root->right):(1<<h-1)+countNodes(root->left);
      int nodes=0,h=height(root);
      while(root!=nullptr)
      {
          if(height(root->right)==h-1)
          {
              nodes+=1<<h;
              root=root->right;
          }else
          {
              nodes+=1<<(h-1);
              root=root->left;
          }
          h--;
      }
      return nodes;
    }
    int height(TreeNode* root)
    {
        return root==NULL?-1:1+height(root->left);
    }

此时的时间复杂度是: O(logn)
原文来自StefanPochmann,自己翻译了下,加点注解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值