👋 欢迎阅读

🎯 欢迎来到「整数替换」题解之旅! 本文将带你从"通过加减和除法将整数变为1"这一数字变换问题出发,深入理解贪心算法 + 位运算 的巧妙运用,并掌握如何通过分类讨论奇偶性来高效求出最小操作次数。
在开始之前,建议你先:
-
了解题目背景 :这是 LeetCode 397 题,给定正整数 nn,若为偶数则除以 2,若为奇数则可选择加 1 或减 1,求将 nn 变为 1 所需的最小操作次数 。本质上,这是一个最短路 问题,但由于数据范围可达 231−1231−1,我们需要用贪心策略而非 BFS,核心在于对奇数的加/减 1 做出最优选择------当 n≡3(mod4)n≡3(mod4) 且 n>3n>3 时,加 1 更优(因为能更快地产生连续除法);否则减 1 更优。
-
明确学习目标 :掌握贪心决策规则------偶数直接除以 2;奇数时,判断 n%4n%4 的值:若为 3 且 n>3n>3,选择加 1(n+1n+1 会变成 4 的倍数,连续除以 2 两次),否则选择减 1(使数变小且不影响后续的整除效率)。同时理解为什么 n=3n=3 是特例(3→2→13→2→1 需 2 步,优于 3→4→2→13→4→2→1 的 3 步)。
-
准备好环境 :建议在本地 IDE 或 LeetCode 在线编辑器中打开代码,边看边运行,亲手验证示例(如
n = 7输出4,n = 8输出3)。
本文将从问题转化、贪心决策规则推导(模 4 分析)、位运算优化 到代码实现,层层递进。即使你对贪心算法还不熟悉,我们也会从"怎样让数字尽快变成 1"这一直觉出发,让你轻松抓住核心思想 ------偶数直接除以 2 是最快的;奇数时,选择加 1 或减 1 要看哪种方式能制造出更多连续的除以 2 机会。现在,让我们一起通过最少的变换,把这个整数"归约"到 1 吧! 🔢🔄
一、题目

二、做题思路
1. 问题分析(前置分析)
给定正整数 n,允许两种操作:
-
若
n为偶数,只能 除以 2; -
若
n为奇数,可以选择 加 1 或 减 1 。目标是用 最少的操作次数 将
n变为1。核心贪心思想 :偶数时直接除以 2 是最优的(唯一选择)。奇数时 ,加 1 或减 1 都会变成偶数,随后可除以 2。为了尽快缩小数字,应优先选择能让后续连续除以 2 更多次的操作 ,即尽量使结果成为 4 的倍数 (因为 4 的倍数可以连续除以 2 两次)。因此根据
n % 4的值决定加 1 还是减 1。
2. 贪心策略(核心决策规则)
-
初始化操作次数
ret = 0。 -
循环直到
n == 1:-
若
n为偶数:直接除以 2 ,ret++。 -
若
n为奇数:-
特殊情况 :若
n == 3,则 减 1 再除以 2 (即3 -> 2 -> 1)只需 2 步,比加 1 的 3 步更优,单独处理ret += 2, n = 1。 -
若
n % 4 == 1:则 减 1 后得到 4 的倍数,可连续除以 2 两次,执行n = (n - 1) / 2,ret += 2。 -
若
n % 4 == 3:则 加 1 后得到 4 的倍数,执行n = n / 2 + 1(等价于(n+1)/2),ret += 2。
-
-
-
返回
ret。
3. 正确性说明(简单版本)
偶数时除以 2 是唯一操作,必然最优。对于奇数,减 1 或加 1 都会产生偶数,随后可以除以 2。为了最小化总步数,应选择那个能产生更多连续除以 2 机会的操作。
-
当
n % 4 == 1时(如 5, 9),减 1 后变为 4 的倍数,能连续除以 2 两次;加 1 后变为n+1,只多一次除以 2,显然减 1 更优。 -
当
n % 4 == 3时(如 7, 11),加 1 后变为 4 的倍数,能连续除以 2 两次;减 1 后变为n-1,只多一次除以 2,加 1 更优。 -
n == 3是特例,因为加 1 得到 4 虽能除以 2 两次,但总共需 3 步;减 1 得到 2 再除以 2 只需 2 步,因此单独处理。这种 "尽可能产生 4 的倍数" 的贪心策略,保证了每次操作都选择当前局部最优,最终得到全局最优解。
4. 实现细节(边界防护)
-
使用
long long类型存储n,防止n+1溢出(但题目n ≤ 2^31-1,n+1可能溢出,需注意,但代码中直接对奇数操作,n/2+1等不会溢出,不过建议使用long long更安全)。 -
循环条件为
n > 1,逐步减少直到 1。 -
偶数时直接除以 2。
-
奇数时先判断
n == 3,再根据n % 4决定操作,每次操作计为 2 步(因为加/减 1 和随后的除以 2 共两次操作)。 -
最终返回
ret。
5. 返回值(目标映射)
返回 ret,即 n 变为 1 所需的最少操作次数。
四、代码
cpp
class Solution
{
public:
int integerReplacement(int n)
{
// 贪心策略:对于偶数,直接除以2(最优);对于奇数,根据 n % 4 的值决定加1还是减1,
// 因为加1或减1都会产生偶数,随后可以进行除以2操作,而不同的选择会影响后续的步数。
// 数学结论:
// - 当 n % 4 == 1 时,减1后除以2比加1后除以2更优(因为减1后变成4的倍数,能连续除以2多次);
// - 当 n % 4 == 3 时,加1后除以2更优(但 n == 3 是个例外,此时减1再除以2只需2步,而加1需要3步)。
// 因此贪心处理:优先让 n 变为能被4整除的数(或接近4的倍数),以加速除以2的过程。
int ret = 0; // 操作次数
while (n > 1)
{
if (n % 2 == 0)
{
// 偶数:直接除以2,操作一次
n = n / 2;
ret++;
}
else // n 为奇数
{
// 特殊情况:n == 3 时,先减1再除以2(即 3 -> 2 -> 1)只需2步,
// 而加1再除以2(3 -> 4 -> 2 -> 1)需要3步,所以单独处理。
if (n == 3)
{
ret += 2; // 两步操作:n-1 然后除以2,直接变为1
n = 1;
}
// 如果 n % 4 == 1,则 n-1 后能被4整除,可以连续除以2两次,减少总步数
else if (n % 4 == 1)
{
// 执行两次操作:先减1,再除以2(相当于 (n-1)/2,但为了统计步数,直接算两次)
n = (n - 1) / 2;
ret += 2;
}
// 如果 n % 4 == 3,则 n+1 后能被4整除,同样能连续除以2两次,
// 但操作顺序是先加1再除以2,等价于 n/2 + 1(整数除法向下取整,但这里 n 为奇数,n/2 为整数部分)
// 注意:加1再除以2 = (n+1)/2,因为 n 是奇数,(n+1)/2 正好等于 n/2 + 1(整数除法)。
else if (n % 4 == 3)
{
n = n / 2 + 1; // 等价于 (n+1)/2
ret += 2;
}
}
}
// 返回最少操作次数
return ret;
}
};
五、流程图
六、正确性说明(详细版)
步骤 1:符号与问题建模
+----------------------------------------------------+
| 输入:正整数 n |
| 操作:偶数 -> n/2;奇数 -> n+1 或 n-1 |
| 目标:使 n 变为 1 的最少操作次数 |
+----------------------------------------------------+
|
v
+----------------------------------------------------+
| 贪心策略: |
| ① 若 n 为偶数,直接除以2(**唯一可行操作**)。 |
| ② 若 n 为奇数: |
| - 若 n == 3,则 n-1 后除以2 只需两步, |
| 而 n+1 需要三步,因此选择 n-1。 |
| - 若 n % 4 == 1,则 n-1 后得到 4 的倍数, |
| 能连续除以2两次,优于 n+1(只除一次), |
| 因此选择 n-1。 |
| - 若 n % 4 == 3,则 n+1 后得到 4 的倍数, |
| 能连续除以2两次,优于 n-1,因此选择 n+1。 |
| 贪心实质:**尽可能让数变成4的倍数**,以连续进行 |
| 两次除以2操作,从而快速缩小数值。 |
+----------------------------------------------------+
-
偶数:只能除以2,无选择余地,贪心直接执行。
-
奇数 :需要决策加1还是减1。选择能使下一步得到的数更小或含有更多因子2的方向,因为除以2是唯一能快速减小的操作。
步骤 2:关键性质 ------ 贪心选择的正确性(分类讨论与反证法)
+----------------------------------------------------+
| 性质 1(偶数直接除2):对于偶数 n,任何最优解 |
| 的第一步都必须是 n/2。 |
| 反证:若先加1或减1得到奇数,再操作,至少需要 |
| 两次才能回到偶数,而直接除以2只需一次,且数值更小,|
| 因此直接除以2必然最优。 |
+----------------------------------------------------+
|
v
+----------------------------------------------------+
| 性质 2(n%4==1 时减1更优):若 n ≡ 1 (mod 4), |
| 则 n-1 是 4 的倍数,可连续除以2两次; |
| 而 n+1 只被2整除一次后变成奇数。因此减1比加1 |
| 能多进行一次除以2,总步数更少。 |
| 反证:若选择加1,则得到 (n+1)/2,它比 (n-1)/2 |
| 大,且少了一次连续的除以2,后续不可能补偿。 |
+----------------------------------------------------+
|
v
+----------------------------------------------------+
| 性质 3(n%4==3 时加1更优,但 n=3 例外): |
| 若 n ≡ 3 (mod 4) 且 n > 3,则 n+1 是 4 的倍数, |
| 能连续除以2两次,而 n-1 只除一次就变奇数。 |
| 因此加1更优。 |
| 特殊 n=3:减1后直接到2,再除2到1,共2步; |
| 而加1后3->4->2->1,共3步,故减1更优。 |
| 反证:对 n>3 若选择减1,则得到 (n-1)/2,它 |
| 是奇数,后续还要再处理,而加1得到 (n+1)/2 是偶数,|
| 可继续除2,显然加1更优。 |
+----------------------------------------------------+
详细论证:
-
性质1 :偶数
n只能进行除以2操作,其他操作(如先减1)会变成奇数,需要更多步骤才能回到偶数,且数值不会更小。因此直接除以2是唯一且最优的选择。 -
性质2 :设
n = 4k + 1。若选择n-1 = 4k,则一次操作后得到4k,再除以2得2k,再除以2得k(若k>1可继续)。而选择n+1 = 4k+2,一次操作后得到奇数2k+1,只能再执行一次加/减操作才能继续除以2。因此减1至少节省一步操作,所以减1更优。 -
性质3 :设
n = 4k + 3(k ≥ 1)。选择n+1 = 4k+4 = 4(k+1),可连续除2两次;选择n-1 = 4k+2 = 2(2k+1),除一次后得奇数2k+1,无法立即再除2。故加1更优。但n=3(k=0)时,减1得2,再除2得1,只需2步;加1得4,再除2得2,再除2得1,需3步,因此n=3必须单独处理,选择减1。
步骤 3:归纳证明 ------ 贪心逐步构造全局最优
+----------------------------------------------------+
| 初始:当前值 n,步数 ret=0。 |
| 归纳假设:每次贪心操作后,剩余问题与原问题同构, |
| 且贪心选择使得当前值在所有最优解中**最小** |
| (或为最优方向)。 |
+----------------------------------------------------+
|
v
+----------------------------------------------------+
| 每次循环: |
| - 若 n 为偶数,由性质1,**必须除以2**。 |
| - 若 n 为奇数且 n>3: |
| * 若 n%4==1,由性质2,**必须减1**(然后除以2)。|
| * 若 n%4==3,由性质3,**必须加1**(然后除以2)。|
| - 若 n==3,**必须减1**(直接到2,再除2)。 |
| 每次操作后 n 严格减小,归纳假设保持。 |
+----------------------------------------------------+
|
v
+----------------------------------------------------+
| 当 n == 1 时,ret 即为最小操作次数。 |
| 因为每一步的选择都是强制或最优的,不存在其他路径 |
| 能比贪心更少步数。 |
+----------------------------------------------------+
详细论证:
-
归纳基础 :当
n=1时,无需操作,ret=0,显然最优。 -
归纳步骤 :假设当前
n > 1,且之前所有贪心选择都使得n以最快速度减小。考虑所有可能的操作:-
若
n为偶数,唯一可执行的操作是除以2,因此这一步是强制性的,贪心必然最优。 -
若
n为奇数且n>3:-
若
n%4==1,由性质2,减1后能连续除2两次,而加1只能除一次,因此任何最优解的第一步都必须减1(否则需要额外步骤补偿),贪心选择正确。 -
若
n%4==3,由性质3,加1后能连续除2两次,减1则不行,因此任何最优解的第一步都必须加1,贪心选择正确。
-
-
若
n==3,分别计算两种路径:3->2->1(2步) vs3->4->2->1(3步),减1明显更优,且是唯一的更优选择。
-
-
每次操作后,
n的值都变为一个更小的正整数,且贪心选择不会排除任何潜在的最优解(因为我们已经证明了选择的必要性)。因此归纳成立 ,最终得到的ret即为全局最小操作次数。
🎯 闭幕

🎉 恭喜你完成了「整数替换」问题的学习!
为了巩固知识并进一步拓展,建议你:
🚀 动手实践
在 LeetCode 上提交代码,尝试不同的测试用例。
💡 深入思考
-
本题采用 贪心 + 位运算 策略:偶数直接除以 2;奇数时,若
n % 4 == 1则减 1,若n % 4 == 3则加 1(但n == 3例外)。为什么优先让奇数变为 4 的倍数能减少总操作次数? 你能从"连续除以 2"的角度解释吗? -
代码中
n == 3时直接返回ret += 2,即走3 -> 2 -> 1只需 2 步,而按n%4==3加 1 则需 3 步。如果不单独处理 3,贪心是否失效? 请用例子验证。 -
本题也可以用 BFS 或 记忆化 DFS 求解,但复杂度较高。贪心为什么能保证最优解? 你能找到反例证明贪心一定正确吗?
-
如果
n是偶数,直接除以 2 显然是最优的。但如果在除以 2 之前先加 1 或减 1,有没有可能更快到达 1? 为什么不可能?
📚 延伸挑战
- 尝试用 动态规划 或 BFS 实现本题,对比贪心的简洁性,在
n <= 1000的小范围验证贪心结果是否正确。
如果你觉得本文对你有所帮助,欢迎:
👍 点赞 / 收藏
👤 关注作者,获取更多题解
💬 留言交流你的疑问或优化思路
祝你在 算法之路 上越走越稳,早日攻克每一道难题!下次见 🚀✨