一、模拟算法
定义:模拟算法是指按照问题的描述或规则,一步步模拟真实过程,最终得到结果的算法。它通常不涉及复杂的数学优化,而是直接模拟问题的执行流程。
特点:
- 逐步执行:按照问题的步骤一步步计算或模拟。
- 直观易懂:代码通常直接对应问题的描述。
- 适用于流程类问题:如游戏规则模拟、物理过程模拟、时间驱动事件等。
示例:模拟报数问题(约瑟夫环问题)
问题:有 n 个人围成一圈,编号从 1 到 n,从编号为 1 的人开始顺时针报数,每报到第 k 个人时,该人出局(被杀、被移除),然后从下一个人重新开始报数,直到所有人都出局。
def josephus(n, k):
people = list(range(1, n + 1))
result = []
idx = 0
while people:
idx = (idx + k - 1) % len(people) # 计算要移除的位置
result.append(people.pop(idx))
return result
print(josephus(7, 3)) # 输出:[3, 6, 2, 7, 5, 1, 4]
-
直接模拟报数过程,每次计算要移除的人的位置,并更新索引。
二、贪心算法
定义
贪心算法在每一步选择当前最优解,期望最终得到全局最优解。它适用于具有最优子结构的问题(即局部最优能导致全局最优)。
特点
- 局部最优选择:每一步只考虑当前最佳选择,不回溯。
- 高效但不一定最优:适用于某些特定问题(如最小生成树、最短路径等),但不适用于所有问题(如0-1背包问题)。
- 需要证明正确性:贪心策略是否真的能得到全局最优解需要数学证明。
示例
问题:用最少数量的硬币凑出指定金额(假设硬币无限)。
# 用最少数量的硬币凑出指定金额(假设硬币无限)
def coin_change(coins, amount):
select_ = []
coins.sort(reverse=True) # 从大到小排序
count = 0
for coin in coins:
while amount >= coin:
amount -= coin
select_.append(coin)
count += 1
return count if amount == 0 else -1 ,select_ # 如果无法凑出,返回-1
coins = [1, 5, 10, 25]
amount = 63
print(coin_change(coins, amount)) # 输出:(6(25+25+10+1+1+1))
-
每次选择最大的硬币,直到凑够金额。