1. 问题定义
我们被给定一个数字 N
,需要将其减少到 1,使用尽可能少的操作。允许的操作包括:
- 加1:当前数字变为
N + 1
- 减1:当前数字变为
N - 1
- 除以2(仅当数字为偶数时):当前数字变为
N / 2
例如:
若
N = 28
,最优路径为:28 → 14 → 7 → 8 → 4 → 2 → 1
(共6步)若
N = 13
,最优路径为:13 → 12 → 6 → 3 → 2 → 1
(共5步)
2. 非最优贪心解法(Greedy)
思路
- 如果
N
是偶数,就除以2 - 如果
N
是奇数,就减1
示例
N = 10
,路径为:10 → 5 → 4 → 2 → 1
(共4步)
缺陷
该方法不总是最优。例如:
N = 15
,贪心路径为:15 → 14 → 7 → 6 → 3 → 2 → 1
(共6步)
但更优路径是:15 → 16 → 8 → 4 → 2 → 1
(共5步)
✅ 结论:速度快,但不保证最优解
3. BFS 解法(广度优先搜索)
思路
将每个数字视为图中的一个节点,节点之间通过加1、减1、除以2(偶数时)连接。
使用 BFS 搜索最短路径。
实现(伪代码)
algorithm BFSApproach(N):
answer <- new array of size 2*N initialized to infinity
queue <- new queue
answer[N] <- 0
queue.push(N)
while not queue.empty():
current <- queue.pop()
if current == 1:
break
for next in [current+1, current-1, current/2 if even]:
if answer[next] > answer[current] + 1:
answer[next] = answer[current] + 1
queue.push(next)
return answer[1]
复杂度
- 时间复杂度:
O(N)
,其中N
是起始数字 - 空间复杂度:
O(N)
✅ 优点:能保证最优解
❌ 缺点:效率不如贪心,尤其在大数时
4. 最优贪心解法(Optimal Greedy)
理论基础
- 如果
N
是偶数 → 除以2 - 如果
N
是奇数:- 若
N == 3
或N % 4 == 1
→ 减1 - 否则 → 加1
- 若
示例
N = 15
:15 % 4 == 3
→ 加1 →16
16 → 8 → 4 → 2 → 1
(共5步)
实现(伪代码)
algorithm OptimalGreedyApproach(N):
answer <- 0
while N > 1:
if N is even:
N = N / 2
else if N == 3 or N % 4 == 1:
N = N - 1
else:
N = N + 1
answer += 1
return answer
复杂度
- 时间复杂度:
O(log N)
- 空间复杂度:
O(1)
✅ 优点:高效且最优
✅ 适用场景:大数场景下的最优解查找
5. 总结
我们讨论了三种方法来解决“将数字减少到1”的问题:
方法 | 是否最优 | 时间复杂度 | 适用场景 |
---|---|---|---|
贪心法(非最优) | ❌ | O(log N) | 快速近似解 |
BFS | ✅ | O(N) | 小数字、需最优解 |
最优贪心法 | ✅ | O(log N) | 大数字、需最优解 |
✅ 推荐:使用最优贪心法,兼顾效率和准确性
⚠️ 注意:在 N == 3
时要特殊处理(减两次)