面试官:"讲一下贪心算法吧。"
我:"额..."(手指不自觉地敲了两下桌子,大脑开始紧急检索)
什么是贪心算法?
想象你在玩一个捡金币的游戏,规则是:每次只能捡离你最近的那枚金币。贪心算法就是这种"每次只选眼前最好"的策略。
举个生活例子:零钱兑换
情况1:能用贪心法
你有面额1元、2元、5元的硬币,要凑11元,最少需要几个硬币?
贪心法做法:
- 先拿最大的5元:还剩6元
- 再拿5元:还剩1元
- 拿1元 总共:3个硬币(5+5+1)✅ 这是最优解
情况2:贪心法会出错
如果只有1元、3元、4元硬币,要凑6元:
贪心法:
- 拿最大的4元:还剩2元
- 拿1元:还剩1元
- 拿1元 总共:3个硬币(4+1+1)❌ 其实最优解是2个3元硬币(3+3)
贪心算法三句话原则
- 眼前最优:每一步都选当前看起来最好的选择
- 不后悔:选了就不回头,不考虑对未来的影响
- 简单快速:计算速度快,但可能不是最佳答案
常见应用场景
-
教室安排:选最多能在同一个教室上的课
- 每次都选最早结束的课,这样能安排更多课
-
找零钱:硬币面额合适时(如1/2/5元)
-
最短路径:导航软件找最近的路
为什么叫"贪心"?
因为它像贪吃的人:
- 看到好吃的(当前最优)就马上吃掉
- 不考虑后面会不会有更好吃的
- 有时候能吃饱(得到最优解),有时候会错过大餐(不是最优解)
代码示例(Python)
# 教室安排问题(选最多课)
def select_class(classes):
# 按结束时间排序
classes.sort(key=lambda x: x[1])
selected = [classes[0]]
for current in classes[1:]:
# 当前课开始时间 >= 最后选的课的结束时间
if current[0] >= selected[-1][1]:
selected.append(current)
return selected
# 测试:每个课是(开始时间,结束时间)的元组
classes = [(1,3), (2,4), (3,5), (4,6)]
print(select_class(classes)) # 输出 [(1,3), (3,5)] 可以选两节课
什么时候能用贪心算法?
记住两个条件:
- 局部最优=全局最优:每一步的最好选择能导致最终最好结果
- 不能反悔:选择后不影响之前的选择
就像考试做题:
- 如果每题独立(做对前一题不影响后一题),可以每题选最有把握的先做(贪心法)
- 如果题目有关联(比如后面要用前面结果),就不能用贪心法
总结一句话
贪心算法就是:"不管以后怎样,现在先拿最好的!" —— 简单粗暴,但有时候很有效。