贪心算法故事:拖延症小明的作业危机

贪心算法就像一位"永远只选眼前最优解"的冒险家,每次决策都选择当下最有利的选项,逐步逼近全局最优解。下面我用一个​​拖延症学生赶作业​​的故事,带你彻底理解其精髓!


📖 ​​故事:拖延症小明的作业危机​​

小明周日晚上才发现有5项作业没做,每项耗时不同:
数学(60分钟), 语文(30分钟), 英语(15分钟), 物理(45分钟), 化学(20分钟)

他要在2小时内(120分钟)完成尽可能多的作业。

⚡ ​​贪心策略​​:

​​每次都选当前耗时最短的作业​​(快速清掉小任务,腾出更多时间)

  1. 选最短:​英语(15min)​ → 剩余时间105min
  2. 选次短:​化学(20min)​ → 剩余85min
  3. 选第三短:​语文(30min)​ → 剩余55min
  4. 选第四短:​物理(45min)​ → 剩余10min
  5. 数学需60min(但剩余时间不足)→ 放弃

​​结果​​:完成4项作业(总耗时110min),比按顺序做(只能做3项)更优!


⚙️ ​​贪心算法核心原理​​

​​1. 两大黄金定律​​

​​特性​​ ​​含义​​ ​​小明例子​​
​​贪心选择性质​​ 局部最优选择能导向全局最优解 每次选最短作业 → 完成总数最多
​​最优子结构​​ 大问题的最优解由子问题最优解组成 完成4项 = 前4项最优解的组合

​​2. 与动态规划的区别​​

💡 贪心永不回溯(高效但可能非全局最优),动态规划会回看历史(准确但更慢)


💻 ​​Java代码实战:作业调度贪心算法​​

typescript 复制代码
java
Copy
import java.util.*;  

public class GreedyHomework {  
    public static void main(String[] args) {  
        // 作业列表:<科目, 耗时>  
        Map<String, Integer> homework = new HashMap<>();  
        homework.put("数学", 60);  
        homework.put("语文", 30);  
        homework.put("英语", 15);  
        homework.put("物理", 45);  
        homework.put("化学", 20);  

        // 贪心核心:按耗时升序排序  
        List<Map.Entry<String, Integer>> sortedList = new ArrayList<>(homework.entrySet());  
        sortedList.sort(Map.Entry.comparingByValue()); // 按耗时排序[11](@ref)  

        // 执行作业  
        int totalTime = 120;  
        List<String> completed = new ArrayList<>();  
        for (Map.Entry<String, Integer> task : sortedList) {  
            if (totalTime >= task.getValue()) {  
                completed.add(task.getKey());  
                totalTime -= task.getValue();  
            } else {  
                break; // 时间不足时停止  
            }  
        }  

        System.out.println("完成作业:" + completed);  
        System.out.println("剩余时间:" + totalTime + "分钟");  
    }  
}  

​​运行结果​​:

css 复制代码
Copy
完成作业:[英语, 化学, 语文, 物理]  
剩余时间:10分钟  

⚠️ ​​贪心算法的陷阱:何时会失效?​​

​​1. 非标准货币找零问题​​

若硬币面额为:[1, 5, 11],要凑出​​15元​​:

  • 贪心:11+1+1+1+1 → ​​5枚硬币​​

  • 实际最优:5+5+5 → ​​3枚硬币​​(贪心失效!)

​​2. 适用条件总结​​

​​场景​​ ​​是否适用贪心​​ ​​原因​​
标准找零(1/5/10) ✅ 是 大面额总能组成最优解
非标准找零 ❌ 否 局部最优≠全局最优
活动安排问题 ✅ 是 早结束的活动优先保证更多安排8
背包问题(物品可分割) ✅ 是 优先选价值密度最高的物品

🚨 ​​黄金法则​ ​:使用前必须证明问题满足​​贪心选择性质​​!


🌐 ​​经典应用场景与Java实现​​

​​1. 活动安排问题(最多不相交区间)​​

ini 复制代码
java
Copy
// 按结束时间排序 → 每次选最早结束的活动[8,10](@ref)  
Arrays.sort(activities, (a, b) -> a.end - b.end);  
int count = 1, lastEnd = activities[0].end;  
for (int i = 1; i < activities.length; i++) {  
    if (activities[i].start >= lastEnd) {  
        count++;  
        lastEnd = activities[i].end;  
    }  
}  

​​2. 股票买卖(多次交易)​​

ini 复制代码
java
Copy
// 只要今天比昨天涨就卖出[5](@ref)  
int profit = 0;  
for (int i = 1; i < prices.length; i++) {  
    if (prices[i] > prices[i - 1]) {  
        profit += prices[i] - prices[i - 1];  
    }  
}  

​​3. 霍夫曼编码(数据压缩)​​

优先合并频率最小的字符 → 构建最优前缀树


💎 ​​总结:一图掌握贪心算法​​

​​面试口诀​​:

眼前利益最大化,全局最优需验证。

活动排序找零钱,子结构是通行证!

试着运行文中的作业调度代码,调整时间限制和作业时长,观察贪心策略的变化。记住:​​贪心算法是面试高频考点,重点在于识别问题是否具备贪心选择性质!​

相关推荐
三少爷的鞋6 小时前
Java 线程自上而下,Kotlin 协程自下而上
android
好的佩奇7 小时前
Dart 之增强枚举
android·flutter·dart
梦影_8 小时前
MySQL进阶教程(五)—— SQL调优(下)
android·大数据·数据库·后端·sql·mysql·database
好的佩奇10 小时前
蓝牙之无线电与通信距离
android·flutter·蓝牙
vilya10 小时前
我把一套完整的 Python Agent 运行时塞进手机 APK:依赖闭包、Rust 轮子和三个真机坑
android
呆呆敲代码的小Y12 小时前
【实战精选面试题】C# 面试题详细解答,按难易程度排序
android·java·游戏·c#·游戏开发·unity面试题·c#面试题
思想觉悟14 小时前
SEAndroid实战
android·linux·c++
思想觉悟14 小时前
Aosp开发磨刀石之ADB速查
android·c++
应用市场17 小时前
用本机跑的开源音乐模型,给安卓小游戏做 20 秒无缝循环背景音乐
android·python·游戏开发·soundpool·音频处理
企业数字化笔记17 小时前
表单发布前怎么验收?版本引用、字段兼容和历史数据回归
android·数据挖掘·回归