397. 整数替换
397. 整数替换
🟠 🔖 贪心 位运算 记忆化搜索 动态规划 🔗 力扣 LeetCode
题目
Given a positive integer n, you can apply one of the following operations:
- If
nis even, replacenwithn / 2. - If
nis odd, replacenwith eithern + 1orn - 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 <= 2^31 - 1
题目大意
给定一个正整数 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
解题思路
递归与记忆化:
- 使用递归方法计算从
n到1的最小操作次数。 - 通过缓存中间结果避免重复计算,加速求解过程。
- 使用递归方法计算从
奇偶处理策略:
- 若
n为偶数,直接递归计算n / 2,所需操作次数为1 + traverse(n / 2)。 - 若
n为奇数,则有两种选择:- 将
n - 1递归转换为1。 - 将
n + 1递归转换为1。
- 将
- 取两者中较小的操作次数。
- 若
复杂度分析
- 时间复杂度:
O(log n),由于记忆化递归避免了大量重复计算,每次减少数值规模。 - 空间复杂度:
O(log n),递归调用栈深度。
代码
/**
* @param {number} n
* @return {number}
*/
var integerReplacement = function (n) {
let cache = new Map();
const traverse = (n) => {
if (n == 1) return 0; // 基础情况
if (cache.has(n)) return cache.get(n);
let operations;
if (n % 2 == 0) {
operations = traverse(n / 2) + 1;
} else {
operations = Math.min(traverse(n - 1), traverse(n + 1)) + 1;
}
cache.set(n, operations); // 缓存结果
return operations;
};
return traverse(n);
};
