zoukankan      html  css  js  c++  java
  • [九度OJ]1113.二叉树(求完全二叉树任意结点所在子树的结点数)

    原题链接:http://ac.jobdu.com/problem.php?pid=1113

    题目描述:

        如上所示,由正整数1,2,3……组成了一颗特殊二叉树。我们已知这个二叉树的最后一个结点是n。现在的问题是,结点m所在的子树中一共包括多少个结点。

        比如,n = 12,m = 3那么上图中的结点13,14,15以及后面的结点都是不存在的,结点m所在子树中包括的结点有3,6,7,12,因此结点m的所在子树中共有4个结点。

    输入:

        输入数据包括多行,每行给出一组测试数据,包括两个整数m,n (1 <= m <= n <= 1000000000)。最后一组测试数据中包括两个0,表示输入的结束,这组数据不用处理。

    输出:

        对于每一组测试数据,输出一行,该行包含一个整数,给出结点m所在子树中包括的结点的数目。

    样例输入:
    3 12
    0 0
    样例输出:
        4
    题解:
      递归版本:
      这道题第一想法是递归,左子树和右子树的结点数和再加1。
    代码如下:
     1 #include <stdio.h>
     2 
     3 int nodeNum_rec(int m,int n)
     4 {
     5      if(m>n)
     6          return 0;
     7     return nodeNum_rec(2*m,n)+nodeNum_rec(2*m+1,n)+1;     
     8 }
     9 int main()
    10 {
    11     int n,m;
    12     int num;
    13     
    14     freopen("tree.in","r",stdin);
    15     freopen("tree.out","w",stdout);
    16     
    17     while(scanf("%d %d",&m,&n)!=EOF&&m&&n)
    18     {
    19 
    20         num=nodeNum_rec(m,n);
    21     
    22         printf("%d
    ",num);
    23     }
    24 
    25     return 0;
    26 }
    View Code

      当题目中n的数目到达十亿级别是,显然这么做会超时的。

      非递归版本:

      这道题的另一种解法是采用非递归,即利用完全二叉树的性质,倒数第二层网上必定是满二叉树,先计算满二叉子树的结点数,然后再根据情况加上剩下的部分。代码如下:

     1 #include <stdio.h>
     2 #include <math.h>
     3 int nodeNum(int m,int n)
     4 {
     5     int deep_n,deep_m;
     6     int sum;
     7     int k;
     8     int start,end; 
     9     
    10     deep_n=log(n)/log(2)+1;//n的高度 
    11     deep_m=log(m)/log(2)+1;//m的高度 
    12     sum=0;
    13     k=1;
    14     //计算到倒数第二层,这几层肯定都是满的,且是按照1、2、4的规律 
    15     for(int i=0;i<deep_n-deep_m;i++){
    16         sum=sum+k;
    17         k=2*k;                    
    18     }
    19     
    20     //计算m的子树在最后一层的起始点和最后节点 
    21     start=m*k;
    22     end=start+k;
    23     if(end<=n)//最后一层也是满的 
    24          sum=sum+k;
    25     else//最后一层不是满的,还差多少补上 
    26     {
    27         
    28            for(int i=start; i<=n; i++)
    29            {
    30                    sum++;     
    31            }
    32            
    33     }
    34     return sum;
    35 }
    36 
    37 int main()
    38 {
    39     int n,m;
    40     int num;
    41     
    42     freopen("tree.in","r",stdin);
    43     freopen("tree.out","w",stdout);
    44     
    45     while(scanf("%d %d",&m,&n)!=EOF&&m&&n)
    46     {
    47 
    48         num=nodeNum_rec(m,n);
    49     
    50         printf("%d
    ",num);
    51     }
    52 
    53     return 0;
    54 }
    View Code
  • 相关阅读:
    金蝶VB插件开发,单据不满足条件,拒绝保存
    继承(子类构造执行的过程)
    Javascript基础(一)
    异常处理(一)
    File I/O(三)
    图片轮播
    java中的foreach循环
    File I/O(一)
    集合框架(三)
    集合框架(二)
  • 原文地址:https://www.cnblogs.com/codershell/p/3306676.html
Copyright © 2011-2022 走看看