贪心算法详细讲解

贪心算法10道经典例题(Java实现,含题意、贪心思路、完整代码)

覆盖区间调度、跳跃游戏、零钱、分发糖果、最优买卖股票、区间合并等面试高频题型,难度由入门到中等,每道题明确贪心选择策略(贪心核心:局部最优→全局最优)。

贪心算法核心思想

每一步做出当前看起来最优的选择,无需回溯、无需考虑后续子问题,多数场景需要排序预处理。

例题1:分发饼干(入门基础)

题目

孩子胃口数组g,饼干尺寸数组s。每块饼干最多给1个孩子,尺寸≥胃口才能满足。求最多能满足几个孩子。

贪心策略

两个数组升序排序,小饼干优先喂胃口小的孩子。

import java.util.Arrays;

public class Solution {

public int findContentChildren(int\[\] g, int\[\] s) {

Arrays.sort(g);

Arrays.sort(s);

int child = 0, cookie = 0;

while(child < g.length && cookie < s.length) {

if(scookie >= gchild) {

child++;

}

cookie++;

}

return child;

}

}

例题2:跳跃游戏Ⅰ

题目

数组每个元素代表当前位置最远跳跃长度,判断能否跳到数组最后一位。

贪心策略

遍历每一格,实时更新能到达的最远下标;最远下标覆盖终点则可行。

public boolean canJump(int\[\] nums) {

int far = 0;

for(int i = 0; i < nums.length; i++) {

if(i > far) return false; // 当前位置无法抵达

far = Math.max(far, i + numsi);

if(far >= nums.length - 1) return true;

}

return true;

}

例题3:跳跃游戏Ⅱ(最少跳跃次数)

题目

数组元素代表最远跳跃距离,保证一定能跳到末尾,求最少跳跃次数。

贪心策略

遍历区间,到达上一轮最远边界时触发一次跳跃,更新新的最远可达位置。

public int jump(int\[\] nums) {

int steps = 0;

int curEnd = 0;

int far = 0;

for(int i = 0; i < nums.length - 1; i++) {

far = Math.max(far, i + numsi);

if(i == curEnd) {

steps++;

curEnd = far;

}

}

return steps;

}

例题4:无重叠区间(区间调度经典)

题目

二维数组intervals,每个区间start, end,求最少移除多少区间,剩余区间互不重叠。

贪心策略

按区间右端点升序排序,优先选结束最早的区间,留给后续更多空间。

import java.util.Arrays;

public int eraseOverlapIntervals(int\[\]\[\] intervals) {

if(intervals.length == 0) return 0;

Arrays.sort(intervals, (a,b) -> a1 - b1);

int count = 1;

int lastEnd = intervals01;

for(int i = 1; i < intervals.length; i++) {

if(intervalsi0 >= lastEnd) {

count++;

lastEnd = intervalsi1;

}

}

return intervals.length - count;

}

例题5:区间合并

题目

若干重叠区间,合并所有重叠区间,返回不重叠区间列表。

贪心策略

按区间起点排序,逐个遍历,能合并就更新右端点,不能合并直接存入结果。

import java.util.*;

public int\[\]\[\] merge(int\[\]\[\] intervals) {

if(intervals.length <= 1) return intervals;

Arrays.sort(intervals, (a,b) -> a0 - b0);

List<int\[\]> res = new ArrayList<>();

res.add(intervals0);

for(int i = 1; i < intervals.length; i++) {

int\[\] last = res.get(res.size()-1);

int\[\] curr = intervalsi;

if(curr0 <= last1) {

last1 = Math.max(last1, curr1);

} else {

res.add(curr);

}

}

return res.toArray(new intres.size()\[\]);

}

例题6:买卖股票的最佳时机(只能一次交易)

题目

数组为每日股价,只能买入一次、卖出一次,求最大利润。

贪心策略

遍历同时记录历史最低价格,每天尝试以当前价卖出,更新最大收益。

public int maxProfit(int\[\] prices) {

int minPrice = Integer.MAX_VALUE;

int maxProfit = 0;

for(int p : prices) {

minPrice = Math.min(minPrice, p);

maxProfit = Math.max(maxProfit, p - minPrice);

}

return maxProfit;

}

例题7:买卖股票的最佳时机Ⅱ(无限次交易)

题目

可无限次买卖股票,不能同时持有多股,求最大利润。

贪心策略

只要后一天股价高于前一天,就当天买入次日卖出,累加所有正差值。

public int maxProfit2(int\[\] prices) {

int profit = 0;

for(int i = 1; i < prices.length; i++) {

if(pricesi > pricesi-1) {

profit += pricesi - pricesi-1;

}

}

return profit;

}

例题8:分发糖果

题目

ratings评分数组,规则:每个孩子至少1颗糖果;评分更高的相邻孩子糖果更多。求最少糖果总数。

贪心策略

两次遍历:左→右保证高分右侧更多;右→左保证高分左侧更多,取两者最大值。

public int candy(int\[\] ratings) {

int n = ratings.length;

int\[\] left = new intn;

int\[\] right = new intn;

Arrays.fill(left, 1);

Arrays.fill(right, 1);

// 左到右

for(int i = 1; i < n; i++) {

if(ratingsi > ratingsi-1) lefti = lefti-1+1;

}

// 右到左

for(int i = n-2; i >= 0; i--) {

if(ratingsi > ratingsi+1) righti = righti+1+1;

}

int sum = 0;

for(int i = 0; i < n; i++) sum += Math.max(lefti, righti);

return sum;

}

例题9:跳跃最少加油次数(加油站贪心)

简化版:到达终点最少加油次数

题意

沿路加油站数组,每个站油量,油箱无限容量,初始油量足够开到第一站,求最少加油次数。

贪心策略:路过站点先不加油,油量不足时,回头选途经油量最大的站点补油。

import java.util.PriorityQueue;

public int minRefuelStops(int target, int startFuel, int\[\]\[\] stations) {

PriorityQueue heap = new PriorityQueue<>((a,b)->b-a);

int fuel = startFuel;

int res = 0;

int prev = 0;

for(int\[\] st : stations) {

int pos = st0, gas = st1;

fuel -= pos - prev;

// 油不够,选之前最大油站加油

while(fuel < 0 && !heap.isEmpty()) {

fuel += heap.poll();

res++;

}

if(fuel < 0) return -1;

heap.add(gas);

prev = pos;

}

fuel -= target - prev;

while(fuel < 0 && !heap.isEmpty()) {

fuel += heap.poll();

res++;

}

return fuel >= 0 ? res : -1;

}

例题10:柠檬水找零

题目

顾客依次付5、10、20元,柠檬水单价5元。手里初始无零钱,能否依次完成所有找零。

贪心策略

收到10元优先用5元找零;收到20元优先组合「10+5」,无10元再用3张5元。

public boolean lemonadeChange(int\[\] bills) {

int five = 0, ten = 0;

for(int b : bills) {

if(b == 5) {

five++;

} else if(b == 10) {

if(five == 0) return false;

five--;

ten++;

} else {

// 20元

if(ten > 0 && five > 0) {

ten--;

five--;

} else if(five >= 3) {

five -= 3;

} else {

return false;

}

}

}

return true;

}

题型分类梳理

  1. 贪心分配类:例题1、例题8、例题10

  2. 跳跃可达类:例题2、例题3

  3. 区间贪心(排序):例题4、例题5

  4. 股票交易贪心:例题6、例题7

  5. 堆优化进阶贪心:例题9

相关推荐
开源Z1 小时前
LeetCode 135 · 分发糖果:两次扫描,先左后右取最大
算法·leetcode
橙序员小站1 小时前
从"夯"到"拉":谷歌苹果华为开发者大会,谁在裸泳?
人工智能·后端
慧都小妮子2 小时前
不想频繁改 PLC?用 DeviceXPlorer Lua 脚本把产线业务逻辑放到 OPC Server 层
java·junit·lua·takebishi·dxpserver·设备数据采集软件·opc server
functionflux2 小时前
kafka-python:Python 生态中最成熟的 Kafka 客户端
分布式·python·其他·kafka
HjhIron2 小时前
从零实现一个待办事项应用:前端必学的Ajax与Node.js实战
前端·后端
迦蓝叶2 小时前
【开源自荐】JAiRouter:一个轻量级 AI 模型服务网关的开源实践
java·人工智能·spring·开源·llm-gateway·mass
浩风祭月2 小时前
我用 AI 辅助重构了遗留项目的认证模块:从明文存储到 OAuth 2.0 的安全升级
后端·php·ai编程