优于线性时间复杂度O(N)获取完全二叉树的总结点数

问题描述

给你一个指向完全二叉树的根节点的指针,返回这棵树的总结点数,要求时间复杂度小于O(n)。

概念介绍

二叉树:

n(n≥0)个节点的有限集,它或为空树(n=0),或由一个根节点和两颗分别称为左子树和右子树的互不相交的二叉树构成

在这里插入图片描述
下面介绍两种特殊形式的二叉树

满二叉树

一颗深度为 k 且有 2 k 2^k 2k - 1 个结点的二叉树称为满二叉树,其特点是每一层上的结点数都是最大结点数。

完全二叉树

深度为 k,有 n 个结点的二叉树当且仅当其每一个结点都与深度为 k 的满二叉树中编号从 1 至 n 的结点一一对应时,称为完全二叉树。
其特点是:

  1. 叶子结点只可能在层次最大的两层上出现
  2. 对任一结点,若其右分支下子孙的最大层次为L,则其左分支下子孙的最大层次必为 L 或 L+1

算法

首先我们要知道:

  1. 深度为 k 的满二叉树含有 2 k 2^k 2k - 1 个结点
  2. 对于一颗完全二叉树,其左右子树至少有一颗为满二叉树

递归地来看,对每一个结点:

1 . 获取它的左子树的高度和右子树的高度
2 . 若高度相同,则左子树必为满二叉树,如下图一,直接计算得到其结点数,递归计算右子树(完全二叉树)的结点数
3 . 若高度不同,则右子树必为满二叉树,如下图二,直接计算得到其结点数,递归计算左子树(完全二叉树)的结点数

在这里插入图片描述

代码

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode() : val(0), left(nullptr), right(nullptr) {}
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

class Solution {
public:
	// 获取完全二叉树的深度
    int getTreeHeight(TreeNode* root){
        if(!root) return 0;
        return 1+getTreeHeight(root->left);
    }
    int dfs(TreeNode* root){
        if(!root) return 0;
        int leftHeight=getTreeHeight(root->left);
        int rightHeight=getTreeHeight(root->right);
        if(leftHeight==rightHeight)
            return 1+pow(2,leftHeight)-1+dfs(root->right);
        else
            return 1+dfs(root->left)+pow(2,rightHeight)-1;
    }
    int countNodes(TreeNode* root) {
        return dfs(root);
    }
};

复杂度

令数的高度为 h,在第1层,操作为获取左右子树的高度,这个过程需要 2*(h-1)次访问,在第二层,需要 2*(h-2)次访问,依次递推,则
O(N) = O( 2 ∗ ( h − 1 + h − 2 + h − 3 + . . . + 2 + 1 ) 2*(h-1 + h-2 + h-3 + ... + 2 + 1) 2(h1+h2+h3+...+2+1) )
=O( 2 ∗ [ ( h − 1 ) ∗ h / 2 ] 2*[ (h-1)*h / 2 ] 2[(h1)h/2] )
=O( h ∗ h h*h hh - h )
=O( h 2 h^2 h2 )
=O( ( l o g N ) 2 (logN)^2 (logN)2 )

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值