java求完全二叉树的节点个数 - 左神算法基础课05 - Kaiqisan

大家好,都吃晚饭了吗?我是Kaiqisan,是一个已经走出社恐的一般生徒,今天讲讲二叉树中比较难的一道题—求二叉树的节点个数

首先还是明确一下概念----何为完全二叉树?

一棵树的节点自上而下,自左而右排列没有空缺的一颗树叫做完全二叉树,设二叉树的深度为k,除第 k 层外,其它各层 (1~k-1) 的结点数都达到最大个数,第k 层所有的结点都连续集中在最左边,这就是完全二叉树。

PS:完全二叉树的特点,完全二叉树的所有子树都是完全二叉树

完全二叉树,因为456从左到右连续
		1
	  /  \ 
	 2    3
	/ \  / 
   4  5  6  
不是完全二叉树因为456从左到右不连续
		1
	  /  \ 
	 2    3
	/ \    \ 
   4  5     6
不是完全二叉树因为第二层没有满
		1
	  /  
	 2    
	/ \     
   4  5     

问题

求一个完全二叉树的节点个数
进阶要求 :时间复杂度为 O(n) – (暗示不能逐个遍历元素)

思路

在这里插入图片描述

先从根节点开始往左无脑遍历(遍历路线1248),先找出该二叉树的最大深度(图中为4)

然后指针撇到它的右孩子(图中从1 -> 3),然后从以3为根节点的子树开始无脑往左遍历(遍历路线为3 6 12)

此时,发现此时12所在的层数为二叉树的最大深度,所以这可以证明以2为根节点的二叉树为满二叉树,又因为确定层数,所以,以二为根节点的二叉树的个数已经确定

然后,我们撇去根节点1 以及以2为根节点的子树

此时已统计的节点达到 2^(4 - 1) = 8个

在这里插入图片描述
然后开始新的统计,从根节点3开始无脑向左遍历(遍历路线 3 6 12),深度为3

然后又向右子树遍历,重复上面的步骤,发现无法遍历到最大的深度

然后,我们撇去根节点13以及以7为根节点的子树

此时统计的节点数达到 8 + 2^( 3 - 1 -1) = 10 个

在这里插入图片描述
然后重复上面的步骤

最终所有的节点遍历结束,一共遍历了12个节点

可能上面的案例在子树这里的数据规模没有那么大了,可能对大家的理解上造成一定的阻碍,我们重新给出两个子树,大家可以进行平行比较!

tree1
在这里插入图片描述
tree2
在这里插入图片描述这两棵树从根节点开始无脑遍历,它们的层数都是4,然后它们往右遍历(先查看右子树,然后从这个右子树开始无脑往左孩子遍历)的时候是不同的
tree2通过遍历路线 3 6 12 可以遍历到最底层,这显然以2为根节点的子树(1的左孩子)就是满二叉树
在这里插入图片描述
tree1无法遍历到根节点
在这里插入图片描述
所以就可以证明以3为根节点的子树(1的右孩子)就是满二叉树

代码

	// 主函数
    static int doSum(Tree head) {
        if (head == null) {
            return 0;
        }
        return exeSum(head, 1, findMostLeftLevel(head, 1));
    }

    static int exeSum(Tree head, int level, int hei) {
        // 遍历到最底层,只有一个元素了
        if (level == hei) {
            return 1;
        }
        if (findMostLeftLevel(head.right, level + 1) == hei) {
            return (1 << hei - level) + exeSum(head.right, level + 1, hei); // <<是位运算符,等同于2的平方
        } else {
            return (1 << (hei - level - 1)) + exeSum(head.left, level + 1, hei);
        }
    }

    static int findMostLeftLevel(Tree head, int level) {
        while (head != null) {
            head = head.left;
            level++;
        }
        return level - 1;
    }

总结

上面的程序的时间复杂度为 O(lg (n))
记得记住思路熬!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kaiqisan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值