废话不多说,直接上题:
#include<stdio.h>
int fun(unsigned int x)
{
if((x >> 1) == 0) return x;
if((x & 1) == 0) return(fun(x/2));
else return(fun(3*x + 1));
}
int main(void)
{
printf("x = %d\n", fun(27));
return 0;
}
问输出是多少?
这咋一看好像是考递归、移位运算、位运算、加减乘除等。好,那就拿纸出来一层层算吧。
方便起见,我就在int fun(unsigned int x)里稍做修改,方便观察x值的变化。
#include<stdio.h>
int fun(unsigned int x)
{
static unsigned int ucCnt = 0;
printf("第%d层: x = %d\n", ++ucCnt, x);
if((x >> 1) == 0) return x;
if((x & 1) == 0) return(fun(x/2));
else return(fun(3*x + 1));
}
int main(void)
{
printf("x = %d\n", fun(27));
return 0;
}
结果:
所以这要是一层层算的话,会非常花时间。如果笔试遇到类似这样的题目,只有短短的一个小时,显然是不够用的。但如果不是考察计算能力,就只有往技巧这方向去思考问题了。不难看出,在int fun(unsigned int x)里,if((x >> 1) == 0) return x是该函数的递归出口,那么,最终的输出结果会不会始终是1呢?答案是有可能。由于x是unsigned int类型,所以(x >> 1) == 0要成立的话,x的值就只能是0或者1了,而且在fun(unsigned int x)里,return(fun(x/2))是使x的值递减的,return(fun(3*x + 1))是使x的值递增的,所以if((x >> 1) == 0) return x这个递归出口的上一层运算,始终是return(fun(x/2)),发现这一步关键所在后,问题就好解决了。由于x是做÷运算,所以只有当x为0时,return(fun(x/2))传递到下一层时,才会使0传递到递归出口,且return(fun(3*x + 1))里有一个+1的运算,保证了x的值不可能为0,也就是说无论在内部递归了多少层x=0都不会由return(fun(3*x + 1))产生,那就只剩下在递归输入时x的值就是0才会出现输出是0的情况。
综上所述,fun(0) >> 0, fun(大于0) >> 1。