给定一个正整数 n
,你可以做如下操作:
- 如果
n
是偶数,则用n / 2
替换n
。 - 如果
n
是奇数,则可以用n + 1
或n - 1
替换n
。
返回 n
变为 1
所需的 最小替换次数 。
思路:
对于偶数,只有一种方法就是除以2.
对于奇数,存在加一或减一变成偶数的情况,因此需要讨论加一和减一的优势:
对于一个奇数,用二进制表示,最后是11的话,此时加一会变成00,而减一会变成10,对于00和10,除以2以后,一个是0,一个是1,而1那个又需要进行加一减一,因此是11的情况下,加一更好。 而最后是01,此时加一变成10,减一变成00,同样的道理可以知道减一会更好。特殊情况是刚好是3,此时减一除以2是最优解,因此需要单独讨论。而对于一个奇数,想要判断最后是01还是11,只需要对4取模,是3就是11,是1就是01.
思路2:
就是对于暴力递归,利用记忆搜索法吗,用哈希表保存k到1的最小次数,这样后面再遇到k可以直接得出最小次数。哈希表的更新是当前数字不在表中,若在则直接返回结果,若不在则先保存到哈希表在返回结构。
class Solution {
public:
unordered_map<int,int>hash;
// int cut(long long n)
// {
// if(n==1)
// return 0;
// if(hash.count(n)==1)
// {
// return hash[n];
// }
// if(n%2==1)
// {
// int a=cut(n+1);
// int b=cut(n-1);
// hash[n]=min(a,b)+1;
// return hash[n];
// }
// else
// {
// hash[n]=cut(n/2)+1;
// return hash[n];
// }
// };
int integerReplacement(int n) {
//加一和减一能带来什么影响?
//加一再除以二,减一在除以二,会差2.
//尽可能多的除以二,也就是要求加一或减一以后能尽可能多的是偶数
//就是找二进制下第一个一尽可能晚出现
// return cut(n);
int ret=0;
while(n>1)
{
if(n%2==1)
{
if(n==3)
{
return ret+2;
}
if(n%4==3)
{
n=n/2+1;
ret+=2;
}
else
{
n=n/2;
ret+=2;
}
}
else
{
n/=2;
ret++;
}
}
return ret;
}
};