题目来源于leetcode,解法和思路仅代表个人观点。传送门。
难度: 中等
时间:1h
题目
给定一个正整数 n ,你可以做如下操作:
如果 n 是偶数,则用 n / 2替换 n 。
如果 n 是奇数,则可以用 n + 1或n - 1替换 n 。
n 变为 1 所需的最小替换次数是多少?
示例 1:
输入:n = 8
输出:3
解释:8 -> 4 -> 2 -> 1
示例 2:
输入:n = 7
输出:4
解释:7 -> 8 -> 4 -> 2 -> 1
或 7 -> 6 -> 3 -> 2 -> 1
示例 3:
输入:n = 4
输出:2
提示:
1 < = n < = 2 31 − 1 1 <= n <= 2^{31} - 1 1<=n<=231−1
思路
根据题意,一个数变成1,除2是最短的路径。
如果一个数是2的幂次的话,每次都是除2,那么这条路径就是最短的。
如果不是2的幂次,那么在路径中就可能碰上奇数。
如果是奇数,可以进行+1
或-1
操作,但是本质上是把奇数变成一个偶数。
我们考虑这两个偶数,low = n-1
和high = n+1
。
我们贪心地取能除2最多的数即可。
代码
class Solution {
public:
int integerReplacement(int n) {
int ans = 0;
while(n != 1){
//3的话特殊处理一下
if(n == 3){
n = 1;
ans += 2;
}
if(n%2 == 0){
n /= 2;
}else{
long long low = n - 1;
long long high = (long long)n + 1;
while(1){
low /= 2;
high /= 2;
ans++;
if(high%2 == 0 && low%2 == 0){
continue;
}else if(high%2 == 0 && low%2 == 1){
n = high;
break;
}else{
n = low;
break;
}
}
}
ans++;
}
return ans;
}
};
算法复杂度
时间复杂度:
O
(
log
n
)
O(\log n)
O(logn)。每次碰上奇数的时候,相当于同时进行了两条路径的计算(n-1
、n+1
),然后抛弃一条路径。
空间复杂度:
O
(
1
)
O(1)
O(1)。