题目描述
给定一个正整数 n,我们可以执行两种操作:
- 如果
n是偶数:n = n / 2 - 如果
n是奇数:可以选择n = n + 1或者n = n - 1
求把 n 变为 1 需要的最少替换次数。
数据范围:
1 <= n <= 2^31 - 1,需要注意 int 溢出问题。
核心思路(贪心 + 二进制位运算)
偶数没有选择,只能直接除以 2,对应二进制右移一位,消除末尾的 0。 难点在于奇数 :奇数只能 + 1 或者 - 1,我们贪心选择操作后能产生更多末尾 0的方案,末尾 0 越多,后续可以连续除 2,步数更少。
奇数二进制最后一位一定是 1,我们看最后两位:
- 末两位
01(n % 4 == 1):执行n-1,直接消除末尾 1,得到末尾两个 0,可以连续两次除 2。 - 末两位
11(n % 4 == 3):执行n+1,发生进位,连续把一串 1 全部变成 0,一次性消除多个低位 1。
⚠️ 特殊特例 n = 3(二进制 11) 按照上面规则,11应该 + 1 变成 4,路径 3→4→2→1 需要 3 步; 但 3-1=2,路径 3→2→1 只需要 2 步,更优。所以必须单独判断 n == 3,强制走n-1。
cpp
class Solution {
public:
int integerReplacement(int n1) {
int count=0;
long long n=n1;
while(n!=1)
{
if(n%2==0)
n=n/2;
else{
if(n==3)
n-=1;
else if((n & (1 << 1)) != 0)//判断二进制次低位是不是1,末两位11
n+=1;
else
n-=1;
}
count++;
}
return count;
}
};