Given a positive integer n, you can apply one of the following operations:
If n is even, replace n with n / 2.
If n is odd, replace n with either n + 1 or n - 1.
Return the minimum number of operations needed for n to become 1.
Example 1:
Input: n = 8
Output: 3
Explanation: 8 -> 4 -> 2 -> 1
Example 2:
Input: n = 7
Output: 4
Explanation: 7 -> 8 -> 4 -> 2 -> 1
or 7 -> 6 -> 3 -> 2 -> 1
Example 3:
Input: n = 4
Output: 2
Constraints:
- 1 <= n <= 231 - 1
dp[n]是 n 变到 1 的最小步数, 如果 n 是偶数 dp[n] = dp[n/2] + 1, 如果 n 是奇数 dp[n] = min(dp[n-1], dp[n+1]), 注意, 题目本身 1 <= n <= 2.pow(32)-1, 但是如果考虑+1 的情况还是会存在 i32 溢出的问题, 所以还是要用 i64 或者 u32 来处理。
use std::collections::HashMap;
impl Solution {
fn dp(n: i64, cache: &mut HashMap<i64, i32>) -> i32 {
if n == 1 {
return 0;
}
if n % 2 == 0 {
let next = if let Some(c) = cache.get(&(n / 2)) {
*c
} else {
Solution::dp(n / 2, cache)
};
cache.insert(n, next + 1);
return next + 1;
}
let add = Solution::dp(n + 1, cache);
let sub = Solution::dp(n - 1, cache);
cache.insert(n, add.min(sub) + 1);
add.min(sub) + 1
}
pub fn integer_replacement(n: i32) -> i32 {
Solution::dp(n as i64, &mut HashMap::new())
}
}