面试官:讲一下贪心算法吧,我:额...

65 阅读2分钟

面试官:"讲一下贪心算法吧。"

我:"额..."(手指不自觉地敲了两下桌子,大脑开始紧急检索)

什么是贪心算法?

想象你在玩一个捡金币的游戏,规则是:每次只能捡离你最近的那枚金币。贪心算法就是这种"每次只选眼前最好"的策略。

举个生活例子:零钱兑换

情况1:能用贪心法

你有面额1元、2元、5元的硬币,要凑11元,最少需要几个硬币?

贪心法做法:

  1. 先拿最大的5元:还剩6元
  2. 再拿5元:还剩1元
  3. 拿1元 总共:3个硬币(5+5+1)✅ 这是最优解

情况2:贪心法会出错

如果只有1元、3元、4元硬币,要凑6元:

贪心法:

  1. 拿最大的4元:还剩2元
  2. 拿1元:还剩1元
  3. 拿1元 总共:3个硬币(4+1+1)❌ 其实最优解是2个3元硬币(3+3)

贪心算法三句话原则

  1. 眼前最优:每一步都选当前看起来最好的选择
  2. 不后悔:选了就不回头,不考虑对未来的影响
  3. 简单快速:计算速度快,但可能不是最佳答案

常见应用场景

  1. 教室安排:选最多能在同一个教室上的课

    • 每次都选最早结束的课,这样能安排更多课
  2. 找零钱:硬币面额合适时(如1/2/5元)

  3. 最短路径:导航软件找最近的路

为什么叫"贪心"?

因为它像贪吃的人:

  • 看到好吃的(当前最优)就马上吃掉
  • 不考虑后面会不会有更好吃的
  • 有时候能吃饱(得到最优解),有时候会错过大餐(不是最优解)

代码示例(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)] 可以选两节课

什么时候能用贪心算法?

记住两个条件:

  1. 局部最优=全局最优:每一步的最好选择能导致最终最好结果
  2. 不能反悔:选择后不影响之前的选择

就像考试做题:

  • 如果每题独立(做对前一题不影响后一题),可以每题选最有把握的先做(贪心法)
  • 如果题目有关联(比如后面要用前面结果),就不能用贪心法

总结一句话

贪心算法就是:"不管以后怎样,现在先拿最好的!" —— 简单粗暴,但有时候很有效。