实现一个函数,对一个正整数n,算得到1需要的最少操作次数?

来源:互联网 发布:韩剧秘密知乎 编辑:程序博客网 时间:2024/05/23 02:00

转自:http://www.wenwn.com/?p=477

方法一:如果是偶数则向右移动一位,如果是奇数就判断一下+1还是-1次数少.【动态规划】

int operation1(int num) {    int i;int f[num+1];memset(f, 0, sizeof(f));for( i = 2; i <= num; i++) {if( (i&0x1) == 0) {f[i] = 1+f[i>>1];} else {int a = f[(i-1)>>1]+2;int b = 2+ f[(i+1) >>1];[i] = a > b? b:a;}}return f[num];}

时间复杂度为o(n);该算法要每个数都要算一次,然后迭代。


方法2:复杂度可以降低,我们将n转为2进制,
1 当num末尾一位为0,理所当然选择右移一位;
2 当num末尾位为1, xx101和xx001时,对于第一种情况,选择+1,-1的次数一样,对于后者则选择-1。所以对于01的情况,选择-1
3 当num末尾为11, x1011,x0011时, 对于第一种+1,-1一样。对于后者选择+1,所以对于011选择+1;
4 当num末尾为111,10111,00111时,对于第一种选择+1,对于后者选则+1,所以都选择加+1。
num>=3 选择+1

int operation2(int num){int cnt = 0;int tmp = num;while( tmp > 1) {if( (tmp & 0×1) == 0) {cnt++;tmp>>= 1;} else {if( (tmp &0×7) == 0×7) {cnt+=4;tmp +=1;tmp>>=3;} else if( (tmp &0×3 )== 0×3) {cnt+=2;tmp -=1;tmp >>=1;} else if( (tmp &0×1) == 0×1){if( tmp == 0×01) {return cnt;} else {cnt+=2;tmp -=1;tmp >>=1;}}}}return cnt;}

这里的复杂度为num的二进制位数log2(n)