mirror of
https://github.com/ShusenTang/LeetCode.git
synced 2024-09-02 14:20:01 +00:00
45 lines
1.5 KiB
Markdown
45 lines
1.5 KiB
Markdown
# [397. Integer Replacement](https://leetcode.com/problems/integer-replacement/)
|
||
|
||
# 思路
|
||
给定一个正整数n,然后让我们通过变换变为1,求最小的变换步数。变换定义如下:
|
||
* 如果n是偶数,变为n/2;
|
||
* 如果n是奇数,可以变为n+1或者n-1。
|
||
|
||
所以,
|
||
* 若n为偶数,`integerReplacement(n) = 1 + integerReplacement(n >> 1);`
|
||
* 若n为奇数,`integerReplacement(n) = 1 + min(integerReplacement(n - 1), 1 + integerReplacement((n >> 1) + 1));`。
|
||
> 注意若n为奇数那么`((n+1) >> 1) == (n >> 1) + 1`,前者当n为INT_MAX时会溢出而后者不会。
|
||
|
||
一开始我想到用动归,但是发现从前往后更新dp时会很耗时,因为做了很多不必要的计算,所以我们应该从后往前更新dp,也即用递归。
|
||
另外,我们可以用一个hash表cache来存放已经计算出来的值避免重复计算。
|
||
|
||
# 代码
|
||
``` C++
|
||
class Solution {
|
||
private:
|
||
unordered_map<int, int>cache;
|
||
public:
|
||
int integerReplacement(int n) {
|
||
if(n < 2) return 0;
|
||
|
||
if(cache.count(n)) return cache[n];
|
||
|
||
int res = 0, n_back = n;
|
||
if(n & 1)
|
||
res = 1 + min(integerReplacement(n - 1),
|
||
1 + integerReplacement((n >> 1) + 1));
|
||
else{
|
||
// 不断除2直到结果是奇数
|
||
while(!(n & 1)){
|
||
res += 1;
|
||
n >>= 1;
|
||
}
|
||
res += integerReplacement(n);
|
||
}
|
||
cache[n_back] = res;
|
||
return res;
|
||
|
||
}
|
||
};
|
||
```
|