关于小球下落的问题

来源:互联网 发布:java开发文档api 编辑:程序博客网 时间:2024/04/20 04:36

有一棵二叉树,最大深度为D,且所有叶子的深度都相同。所有结点从上到下从左到右编号为1,2,3,...,2^D-1。在结点1处放一个小球,它会往下落。每个内结点上都有一个开关,初始全部关闭,当每次有小球落到一个开关上时,它的状态都会改变。当小球到达一个内结点时,如果该结点上的开关关闭,则往左走,否者往右走,直到走到叶子结点。
一些小球从结点1处依次开始下落,最后一个小球将会落到哪里呢?输入叶子深度D和小球个数I,输出第I个小球最后所在的叶子编号。假设I不超过整棵树的叶子个数(即2^(D-1))。D<=20。输入最多包含1000组数据。
样例输入:
4 2
3 4
10 1
2 2
8 128
16 12345
样例输出:
12
7
512
3
255
36358

分析:建立一个数组,存放每个节点的开关状态,用一个for循环来改变这个状态,即循环每一个小球,初始k=1,若向左,则 k=2*k,向右则 =2*k+1,不难得出最后一个小球落在哪一个节点,但是这样的方法有一个问题,就是若树的节点很多,比如树的深度游19层,则节点数为2^19-1,并且小球个数也可以和叶子数相同,造成大量数据,占用大量内存,换个角度思考,对于每个节点仅有两种状态,若我们知道小球是第几个来的就可以得出左或右,对此我们可以运用递归的思想去思考,初始k=1,对于第1层,判断最后一个小球是第几个来的即判断I是奇数还是偶数,若为奇数,就相当于将I/2 + 1个小球再次放到节点2的子树中再次进行上述判断,若I为偶数,即相当于将I/2个小球放入节点为3的子树中进行上述判断。循环值D-1即可,一共只有D层。代码如下:

whie(scanf(“%d%d”), &D, &I)

{

int k=1;

for(int i=0;i < D-1; ++i)

{
if(I%2)

{

k = k*2;

I = (I+1)/2;

}

else

{

k = k*2 + 1;

I /= 2;

}

}

printf(“%d\n”, k);
}

0 0