题目描述:
求最小的转换次数。
这道题最初的想法就是把所有的情况都算一下,然后比较得出最小的。可以递归解决,直到N变成了1。递归想着要耗费大量时间,没想到也通过了,哈哈。
代码:
int integerReplacement(int n) {
// Write your code here
//普通递归思想,可以通过
if(n <= 1)
return 0;
if(n==2)
return 1;
if(n == 3)
return 2;
if(n%2){
return min(integerReplacement(n+1), integerReplacement(n-1)) + 1;
}
else{
return integerReplacement(n/2) + 1;
}
}
既然递归的想法都能通过,那么还可以尝试进行动态规划的解法,从底向上。想法很好,但是因为申请大量的内存,会爆掉。
想法:buf[i]表示将i转成成1的最少次数。i%2==0 buf[i] = 1+buf[i/2];
i%2==1 buf[i] = min(1+buf[i-1], 2+buf[(i+1)/2])
代码:
int integerReplacement(int n){
if(n<=1)
return 0;
vector<int> buf(n+1, 0);
buf[0] = buf[1] = 0;
buf[2] = 1;
for(int i=3; i<=n; ++i){
if(i%2 == 0){
buf[i] = 1 + buf[i>>1];
}
else{
buf[i] = min(1+buf[i-1] , 2+buf[(i+1)>>1]);
}
}
return buf[n];
}
然后在网上看到了一种基于二进制的解法。很是巧妙,观察末尾为0,说明是偶数,直接右移一位;当末尾为1时,就要分情况讨论。目的就是把尽量多的1变成0,然后通过移位来解决。当从末尾开始,有连续两个及两个以上的1时,执行加一操作,当只是末尾是1时,执行减一操作。这当中有一个特殊情况,当N为3时,减一然后右移是最少的移动次数。
代码:
int integerReplacement(int n) {
// Write your code here
//利用二进制的思想
int count = 0;
while(n != 1){
if((n&1) == 0){
n >>= 1;
}
else if(n==3 || ((n>>1)&1)==0){
--n;
}
else{
++n;
}
++count;
}
return count;
}
参考博客:https://www.jianshu.com/p/4351f30e5f07