基本定义
贪心算法或贪心思想采用贪心的策略,保证每次操作都是局部最优的,从而使最后得到的结果是全局最优的。
分配问题
问题描述:有一群孩子和一堆饼干,每个孩子有一个饥饿度,每个饼干都有一个大小。每个孩子只能吃最多一个饼干,且只有饼干的大小大于孩子的饥饿度时,这个孩子才能吃饱。求解最多有多少孩 子可以吃饱。
输入输出样例
输入: 1 3 5 6
1 2 3 4 5
输出: 2
题解
**因为饥饿度最小的孩子最容易吃饱,所以我们先考虑这个孩子。**为了尽量使得剩下的饼干可以满足饥饿度更大的孩子,所以我们应该把大于等于这个孩子饥饿度的、且大小最小的饼干给这 个孩子。满足了这个孩子之后,我们采取同样的策略,考虑剩下孩子里饥饿度最小的孩子,直到 没有满足条件的饼干存在。
简而言之,这里的贪心策略是,给剩余孩子里最小饥饿度的孩子分配最小的能饱腹的饼干至于具体实现,因为我们需要获得大小关系,一个便捷的方法就是把孩子和饼干分别排序。这样我们就可以从饥饿度最小的孩子和大小最小的饼干出发,计算有多少个对子可以满足条件。
代码实现
import java.util.Arrays;
public class Greedy1 {
public static int solution(int[] child,int[] cookies){
Arrays.sort(child);
Arrays.sort(cookies);
// 定义两个指针,分别指向当前的孩子和饼干,对当前的孩子和饼干进行比较
int childNum = 0;
int cookiesNum = 0;
while (childNum<child.length && cookiesNum<cookies.length) {
if (child[childNum]<=cookies[cookiesNum++]) childNum++;
}
return childNum;
}
public static void main(String[] args) {
int[] child = {1,2,3};
int[] cookies = {1,2,3};
int result = solution(child,cookies);
System.out.println(result);
}
}
区间问题
给定多个区间,计算让这些区间互不重叠所需要移除区间的最少个数。起止相连不算重叠。
输入输出样例
输入是一个数组,数组由多个长度固定为 2 的数组组成,表示区间的开始和结尾。输出一个整数,表示需要移除的区间数量。
输入:[[1,4],[3,7],[4,6],[8,9]]
输出:1
在这个样例中,我们可以移除区间[3,7],使得剩余的区间[[1,4],[4,6],[8,9]]互不重叠。
题解
在选择要保留区间时,区间的结尾十分重要: 选择的区间结尾越小,余留给其它区间的空间就越大,就越能保留更多的区间。
因此,我们采取的贪心策略为,优先保留结尾小且不相交的区间。 具体实现方法为,先把区间按照结尾的大小进行增序排序,每次选择结尾最小且和前一个选 择的区间不重叠的区间,在样例中,排序后的数组为[[1,4],[4,6],[3,7],[8,9]]。按照我们的贪心策略,首先初始化为区间[1,4];由于 [1.4]与[3,7] 相交,我们跳过该区间;由于[1,4]与[4,6] 不相交,我们将其保留,同理,[8,9]也保留。因 此最终保留的区间为 [[1,4],[4,6],[8,9]]
代码实现
public class Greedy2 {
public static int solution(int[][] meetingTime){
Arrays.sort(meetingTime,new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[1]>o2[1]?1:-1;
}
});
int del = 0;
int end = meetingTime[0][1]; // 记录前面一个有效区间的结束位置
for (int i = 1; i < meetingTime.length; i++) {
int start = meetingTime[i][0];
if (start<end) {
del++;
}else{
end = meetingTime[i][1];
}
}
return del;
}
public static void main(String[] args) {
int[][] meeting = {{1,4},{3,7},{4,6},{8,9}};
int result = solution(meeting);
System.out.println(result);
}
}
买股票的最佳时机问题
给定一个数组,它的第i个元素是一支给定股票第 i天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易 (多次买卖一支股票)。
注意: 你不能同时参与多笔交易 (你必须在再次购买前出售掉之前的股票)。
输入输出样例
输入:[7,1,5,3,6,4]
输出:7
解释:在第2天(股票价格=1)的时候买入,在第3天(股票价格=5)的时候卖出,这笔交易所能获得的利润为5-1=4。随后,在第4天(股票价格=3)的时候买入,在第5天(股票价格=6)的时候卖出,这笔交易所能获得利润为6-3=3。
题解
这道题的贪心思想在于如果今天买,明天卖可以赚钱,那么就买入。
代码实现
public class Greedy3 {
public static int solution(int[] stock){
int profit = 0;
for(int i=0;i<stock.length-1;i++){
if (stock[i]<stock[i+1]) {
profit += stock[i+1]-stock[i];
}
}
return profit;
}
public static void main(String[] args) {
int[] stock = {7,1,5,3,6,4};
int profit = solution(stock);
System.out.println(profit);
}
}