AIUnlimited
🌳

AI基础

🌱
AI 种子

从零开始

🌿
AI 萌芽

打好基础

🌳
AI 枝干

付诸实践

🏕️
AI 树冠

深入探索

🌲
AI 森林

精通AI

🔨

AI精通

✏️
AI 草图

从零开始

🪨
AI 雕刻

打好基础

⚒️
AI 匠心

付诸实践

💎
AI 打磨

深入探索

🏆
AI 杰作

精通AI

📘

AI实战

📖
理解开源模型

开源模型的基础知识和资源

🎯
问题到模型任务

将业务问题转化为模型任务

⚡
跑通第一个模型

30分钟快速看到第一个结果

🔧
微调与评测

微调模型并评估性能

🚀
应用系统

构建实际AI应用系统

🎨
生成式AI

探索AIGC的开源模型

🤖
Agent智能体

学习Agent框架和MCP工具

📐
基础补充

LLM基础知识和评测

🎓

Claude 学院

🤖
Claude 101 入门

用 Claude 学习 AI 基础知识

💻
Claude Code 101 入门

让 Claude 成为你的结对编程伙伴

🤝
Claude Cowork 入门

与 Claude 协作完成复杂项目

⚙️
Claude 平台 101

使用 Claude API 构建应用

实验室

已加载 7 个实验
🧬神经网络沙盒🤖AI 还是人类?🥋提示工程道场🏁算法竞速🧠AI 知识挑战🏗️系统设计画布
🎯模拟面试进入实验室→
🚀

职业发展

🚀
面试发射台

开启你的旅程

🌟
行为面试精通

掌握软技能

💻
技术面试

通过编程轮次

🤖
AI与ML面试

ML面试精通

🏆
Offer与未来

拿下最好的Offer

立即开始
AIUnlimited

AI 教育平台

沪ICP备18025655号-11

学习

  • AI基础
  • AI实战
  • Claude学院
  • 实验室
  • 职业发展

社区

  • 关于
  • 常见问题

支持

  • 服务条款
  • 隐私政策
  • 联系我们
AI & 工程学习计划›✏️ AI 草图›课程›贪心算法
🏃
AI 草图 • 中级⏱️ 17 分钟阅读

贪心算法

是什么让算法变得贪婪?

贪心算法构建一个解决方案一次一步,总是选择现在看起来最好的选项 - 而不重新考虑过去的选择。没有回头路,没有向前看。

当两个属性成立时它起作用:

  1. 贪婪选择属性 - 局部最优选择导致全局最优解。
  2. 最优子结构 - 每次选择后剩下的问题是同一问题的较小实例。

活动选择 - 经典示例

给定一组具有开始和结束时间的活动,选择不重叠活动的最大数量。

贪心策略: 按结束时间排序,始终选择最早完成的活动。

def max_activities(intervals):
    intervals.sort(key=lambda x: x[1])
    count, end = 0, 0
    for s, e in intervals:
        if s >= end:
            count += 1
            end = e
    return count

为什么这有效?选择最早完成的活动可以为未来的活动留下最大的空间。没有其他选择可以做得更好。

按最早结束时间显示活动选择的时间线
按最早结束时间进行选择可以最大化非重叠活动的数量。

霍夫曼编码 - 概念

通过重复合并两个最低频率符号来构建最佳的无前缀二进制代码。这是贪婪的:在每一步,合并最便宜的对。结果是一棵树,其中频繁的符号得到短代码。

🤯

霍夫曼编码用于 JPEG、MP3 和 ZIP 压缩。 David Huffman 在 1952 年还是一名学生时发明了它 - 这是一项家庭作业!

跳跃游戏

给定一个数组,其中 nums[i] 是从索引 i 开始的最大跳转长度,确定是否可以到达最后一个索引。

贪婪方法: 跟踪迄今为止可到达的最远索引。从左到右扫描 - 如果落后,则返回 false。

def can_jump(nums):
    farthest = 0
    for i, jump in enumerate(nums):
        if i > farthest:
            return False
        farthest = max(farthest, i + jump)
    return True
🧠小测验

在跳跃游戏中,贪心变量”最远”代表什么?

加油站

沿着有加油站的环形路线行驶。在i站,您获得gas[i]燃料并花费cost[i]到达下一站。找到可以让您完成环路的起始站,或返回−1。

贪婪洞察力:如果总天然气≥总成本,则存在解决方案。追踪持续盈余;每当它低于零时,答案必须在该点之后开始。

任务调度器

在相同任务之间安排冷却时间为 n 的任务。 **贪婪:**总是选择最频繁的剩余任务。答案取决于最大频率以及有多少任务共享它。

第 9 课,共 10 课已完成 0%
←递归与回溯

讨论

登录 参与讨论

Tasks: A A A B B C, cooldown = 2
Schedule: A B C A B _ A
Total = 7
🤔
Think about it:

在任务调度程序中,为什么首先选择最频繁的任务来最小化空闲槽?如果你先选择最不频繁的,会出现什么问题?

分数背包 vs 0/1 背包

**碎片背包:**您可以携带碎片物品。贪婪有效 - 按重量价值排序,首先采用最佳比例。

0/1 背包: 物品要么全有,要么全无。贪婪在这里失败,因为跳过一件重但有价值的物品可能比拿两件轻的物品更糟糕。这就需要动态规划。

Items: (weight=3, value=4), (weight=2, value=3), (weight=2, value=3)
Capacity: 4

Greedy (best ratio first): takes item 1 (w=3, v=4) → 1 remaining → can't fit rest → value = 4
Optimal: takes items 2+3 (w=4, v=6) → value = 6 ✗ Greedy fails!
🧠小测验

为什么贪心方法对于 0/1 背包问题会失败?

贪婪算法什么时候起作用?

✅ 当你可以证明贪婪选择属性时有效:

  • 间隔调度、霍夫曼编码、最小生成树、Dijkstra 算法、标准面额硬币找零

❌ 当局部最优值不能组成全局最优值时,失败:

  • 0/1背包,一般图中最长的路径,旅行推销员

证明贪心的正确性 - 交换论证

标准技术:假设一个不使用贪婪选择的最佳解决方案。表明您可以将其选择之一交换为贪婪的选择,而不会使解决方案变得更糟。这证明贪婪至少同样好。

🧠小测验

”交换论证”有什么用?

贪心与动态规划

|方面|贪心|动态规划| |--------|--------|---------------------| |选择|每一步都有一个最佳选择 |探索所有子问题 | |重温过去? |从来没有|是 - 存储子结果 | |速度|通常更快 |取决于状态空间 | |正确性|仅当可证明时 |始终(如果表述正确)|

如有疑问,请开始贪婪 - 如果您无法证明它有效,请切换到 DP。

🤯

Dijkstra 的最短路径算法是贪婪的 - 它总是处理最近的未访问节点。它之所以有效,是因为边权重是非负的,确保贪婪选择是安全的。

🤔
Think about it:

给你面额为 [1, 3, 4] 的硬币,需要找 6 个硬币。贪婪方法选择 4+1+1=3 个硬币,但最佳选择是 3+3=2 个硬币。这些面值怎么打破贪婪选择属性呢?


📚 进一步阅读

  • NeetCode - 贪婪播放列表 - 策划贪婪问题和解释
  • 技术面试手册 - Greedy - 何时使用贪婪和常见模式
  • CP-算法 - 贪心算法 - 更深入的理论和证明