题目1113:二叉树(二叉树结点问题)

来源:互联网 发布:卷积深度信念网络 编辑:程序博客网 时间:2024/05/22 04:54
题目1113:二叉树

两种方法解决,都利用了二叉树的性质

时间限制:1 秒

内存限制:32 兆

题目描述:

 

 

 


    如上所示,由正整数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 120 0
样例输出:
4
思路:

令父节点的标号为i, 若左孩子存在,那么左孩子的标号为2*i,若右孩子存在,那么右孩子标号为2*i+1。根据这个性质我便一层一层搜,
若不到最后一层,那么当前层的结点便可以全部加上,而不必挨个去计数。其实最后一层也不必挨个去计数,
只要最后一层的尾结点的标号大于最左孩子的标号,那么便可以用尾结点下标剪去最左孩子的下标加1.

#include <iostream>#include<string.h>#include<stdio.h>using namespace std;int main(){    int m,n,sum,left,right;    while(scanf("%d%d",&m,&n)!=EOF&&(m||n))    {      sum=0;      if(m==n) sum=1;      else      {          if(m<=n) sum=1;          left=2*m;          right=2*m+1;          while(n>right)          {              sum+=(right-left+1);              left*=2;              right=right*2+1;          }          if(n>=left) sum=sum+(n-left)+1;      }       printf("%d\n",sum);    }    return 0;}

 方法2

#include <iostream>#include<string.h>#include<stdio.h>#include<math.h>using namespace std; int main(){    long long m,n,sum,left,right;    while(scanf("%lld%lld",&m,&n)!=EOF&&(m||n))    {      sum=0;      int i=0;      left=m;      right=m;      while(right<=n)      {          sum+=int(pow(2.0,i++));          right=right*2+1;//右子树          left*=2;//左子树      }      //下一层右子树不存在时      while(left<=n)      {          sum++;          left++;      }      printf("%lld\n",sum);    }    return 0;} /**************************************************************    Problem: 1113    User: zhuoyuezai    Language: C++    Result: Accepted    Time:0 ms    Memory:1608 kb****************************************************************/

 

0 0
原创粉丝点击