Week3 - 397. Integer Replacement
Week3 - 397. Integer Replacement
397.Integer Replacement - Medium
Given a positive integer n and you can do operations as follow:
1.If n is even, replace n with n/2.
2.If n is odd, you can replace n with either n + 1 or n - 1.
What is the minimum number of replacements needed for n to become 1?
Example 1:
Input:
8
Output:
3
Explanation:
8 -> 4 -> 2 -> 1
Example 2:
Input:
7
Output:
4
Explanation:
7 -> 8 -> 4 -> 2 -> 1
or
7 -> 6 -> 3 -> 2 -> 1
这道题的我的思路一开始是这样的:由于我们的目标是让这个数尽可能快的变成1,因此每一步数字变小的幅度越大,所花的步骤越少。所以整体的思路应该是让总的加减1的次数更少。
我最初的做法是写一个bitcount函数,去数出当步的数字在二进制中有多少个1——1越少说明除以2的次数越多,然后通过比较+1/-1的bitcount结果来选择路径。
然而交上去发现RA。没什么思路的情况下去看了Discussion,用网友的思路AC了。
这个算法是这样的:当n为奇数时,如果(n + 1) % 4 == 0
则取n+1,否则均取n-1。
我自己尝试着证明了一下:
可以看到所列出的4种情况中,它们之间互相存在着互斥的情况,我们只需要在不互斥的情况中选择结果更小的方法即可得到最优策略。具体情况列举如下:
情况1(n+1为奇数):与情况23互斥,结果比情况4大。
情况2(n+1为偶数):与情况14互斥,结果比情况3小。
将情况进行总结,就能得出最优算法,算法的复杂度为O(nlogn);
代码如下:
class Solution {
public:
int integerReplacement(int n) {
int count = 0;
while (n != 1) {
if (n == 3) {
return count + 2;
} else if (n == INT_MAX) {
return 32;
} else if ((n & 1) == 1) {
n = ((n + 1) % 4) ? (n - 1) : (n + 1);
} else {
n /= 2;
}
count++;
}
return count;
}
};
其中,对(n==INT_MAX)的判断是为了防止溢出,因为后面要用到(n+1)%4的判断。