📅  最后修改于: 2023-12-03 15:26:42.301000             🧑  作者: Mango
给定一个整数 N,你可以进行以下操作:
输入: 8
输出: 3
解释: 8 -> 4 -> 2 -> 1
根据题目的描述,我们可以列举出对于不同的 N,可能进行的操作和对应的代价:
| 操作 | 代价 | | ---- | ---- | | N/2 | 1 | | N+1 | 1 | | N-1 | 1 |
由此,我们可以得到一个简单的贪心策略:每次选择能够使得 N 除以 2 的操作,如果不能,则选择加 1 或减 1 的操作。
对于这种贪心策略的正确性,我们可以证明:如果 N 是偶数,则除以 2 显然比加 1 或减 1 的操作更优;如果 N 是奇数,我们进行加 1 或者减 1 操作后得到的是偶数,相当于除以 2,因此依然是最优的选择。
但是这种贪心策略有一个问题,当 N 是负数时会进入死循环,因此我们需要在代码中进行处理。
def min_cost_to_one(n: int) -> int:
if n < 1:
return 0
cost = 0
while n != 1:
if n % 2 == 0:
n = n // 2
elif n == 3 or ((n - 1) & (n - 2)) > ((n + 1) & n):
n -= 1
else:
n += 1
cost += 1
return cost
时间复杂度:$O(\log n)$,可以证明最多只需要进行 $O(\log n)$ 次操作。
空间复杂度:$O(1)$。
本题利用了贪心算法的思想,通过列举不同的操作代价并设计一个贪心策略,找到了使得操作数最小的方案。这种思路在解决优化问题时常常能够发挥作用。