转自: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);该算法要每个数都要算一次,然后迭代。
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)