求完全二叉树的结点个数

举报
兔老大 发表于 2021/04/26 00:59:54 2021/04/26
【摘要】 第一次见这个题,看时间小于O(N)。。。。。 只能是二分啊。 但是怎么二分,条件是什么,真的想不到。   后来知道了,我们要找最深一层最右边那个结点。借此确定结点个数。   我们知道,满二叉树的结点个数和深度是有公式的,那么我们找到最后一层最右边的结点,其实就可以确定结点个数。 目标:找箭头指向的结点。   我们采用二分...

第一次见这个题,看时间小于O(N)。。。。。

只能是二分啊。

但是怎么二分,条件是什么,真的想不到。

 

后来知道了,我们要找最深一层最右边那个结点。借此确定结点个数。

 

我们知道,满二叉树的结点个数和深度是有公式的,那么我们找到最后一层最右边的结点,其实就可以确定结点个数。

目标:找箭头指向的结点。

 

我们采用二分法:

1)找到右子树的最左结点

如果右子树深度为3(4-1),说明图中最后的1是存在的(说明最后一行最右结点一定来自右子树),否则

右子树深度为2!=4-1,不存在最后一行的结点。(说明最后一行最右结点一定来自左子树).

 

判断之后,如果是这种情况,我们排除了左子树,计算排除的结点个数(如图),并对右子树做相同的处理。

更新结点数(未被框起的部分,满二叉树公式+1)+1是根结点

对方框内重复此过程。

我们继续看右子树,发现右子树深度为1!=3-1.

说明最深层最右结点来自于左子树。所以对左子树重复上述过程

我们发现,右子树深度=1=2(整棵树深度)-1,说明最深层最右结点来自于右子树,所以对右子树重复此过程。

最终找到它

 

我们再回忆一下过程:

 

1)找到右子树最左节点,确定了深度,对右子树重复。

2)找到右子树最左节点,确定了深度,对左子树重复。

3)找到右子树最左节点,确定了深度,对右子树重复。

4)找到

 

过程中可以

1)把排除的部分全部加起来,

2)也可以记录每次的选择(向左还是向右),最终100010这种字符,其实就是最后一层的结点个数。

 

贴上方法1的全部代码:


  
  1. public class Demo {
  2. public static class Node {
  3. public int value;
  4. public Node left;
  5. public Node right;
  6. public Node(int data) {
  7. this.value = data;
  8. }
  9. }
  10. //返回结点个数
  11. public static int nodeNum(Node head) {
  12. if (head == null) {
  13. return 0;
  14. }
  15. return bs(head, 1, mostLeftLevel(head, 1));
  16. }
  17. //返回根为node,当前层数为l,总深度为h的结点个数
  18. public static int bs(Node node, int l, int h) {
  19. if (l == h) {
  20. return 1;
  21. }
  22. if (mostLeftLevel(node.right, l + 1) == h) { //右子树最深一行最左为空
  23. return (1 << (h - l)) + bs(node.right, l + 1, h); //右bs+左子树结点个数
  24. } else { //右子树最深一行最左不为空
  25. return (1 << (h - l - 1)) + bs(node.left, l + 1, h);//左bs+右子树结点个数
  26. }
  27. }
  28. //计算树的高度
  29. public static int mostLeftLevel(Node node, int level) {
  30. while (node != null) {
  31. level++;
  32. node = node.left;
  33. }
  34. return level - 1;
  35. }
  36. public static void main(String[] args) {
  37. Node head = new Node(1);
  38. head.left = new Node(2);
  39. head.right = new Node(3);
  40. head.left.left = new Node(4);
  41. head.left.right = new Node(5);
  42. head.right.left = new Node(6);
  43. System.out.println(nodeNum(head));
  44. }
  45. }

 

文章来源: fantianzuo.blog.csdn.net,作者:兔老大RabbitMQ,版权归原作者所有,如需转载,请联系作者。

原文链接:fantianzuo.blog.csdn.net/article/details/84289179

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。