leetcode——Count Complete Tree Nodes

题目

Count Complete Tree Nodes
Given a complete binary tree, count the number of nodes.

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.

方法

题目是要得到一颗完全二叉树的节点个数。一般情况下,遍历一遍相信大家都能得到结果,同时如果这样的话,这篇文章就白费了。

我们知道比O(n)性能更好的复杂度为O(logn)。因此,本文重点讲解如何让复杂度为O(logn)。

完全二叉树的定义不再赘述,根据完全二叉树的定义可知:我们可以根据叶子节点的分布来对这个二叉树进行二分查找分界点,这个分界点就是第一个在倒数第二层的叶子节点或只有左孩子的节点。

这里写图片描述

代码

图中,序号代表要依次探索的节点顺序。首先,在根节点,找到A子树和B子树的最右侧高度:A为2(从A到D节点),B为2(从B到最右侧叶子节点)。
由于高度相同,说明分界点 在A子树上。因此d要第2步考虑的节点即为A节点。同理,C子树高度2,D子树高度1,由于高度不一样,则分界点在D子树上,下一个节点即为D。由于D的左右子树都没有孩子,说明它是叶子节点。因此,第三步的时候就找到了这个分界点。

要注意的是:每当考虑的节点从父节点变为右子节点的时候,就说明左侧的所有叶子节点都是满的,则可以通过当前所在的层数和总层数计算出叶子的个数。这样,每次我们的目标成为右子节点的时候,就可以把当前节点为根节点的左子树的叶子节点计算出来,在最终加上。而当目标节点从父节点变为左子结点的时候,说明我们算出来的两个高度是相同的,也就是说,目标节点一定不是分界点,因此也就不用,也不能计算左侧的叶子节点。

代码

public class Count_Complete_Tree_Nodes {
    public int leftHight(TreeNode rootNode){
        int h = 0;
        while(rootNode!=null){
            h++;
            rootNode = rootNode.left;
        }
        return h;
    }
    public int rightHight(TreeNode rootNode){
        int h = 0;
        while(rootNode!=null){
            h++;
            rootNode = rootNode.right;
        }
        return h;
    }

    public int countNodes(TreeNode root) {
        int level = leftHight(root);
        int levelRight = rightHight(root);
        if(level==levelRight){
            return (1<<levelRight)-1;
        }
        TreeNode curNode = root;
        int curLevel = 0;
        int leaf = 0;
        while(curNode.left!=null && curNode.right!=null){
            curLevel++;
            int l = rightHight(curNode.left);
            int r = rightHight(curNode.right);
            if(l!=r){//不同向右
                curNode = curNode.right; 
                leaf+=Math.pow(2, level-1-curLevel);//收下左边的叶子

            } else{//相同向左
                curNode = curNode.left;
            }
        }

        if(curNode.left==null){
            return leaf+(1<<levelRight)-1;
        } else{
            return leaf+(1<<levelRight);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值