目录
案例分析
纸币数量
分析:需要最少纸币张数,因次每次都选用最大面值的纸币,所以贪心策略即是此.当然其中还是有些小细节,比如当所需支付的钱小于纸币面值,亦或是当前面值纸币数量不够.
由于没有找到在线OJ题,因此自己写函数测试下:
public class test {
public static int solve(int money, int[][] moneyCount){
int num = 0;
//贪心策略,先从面值大的开始计算
for (int i = moneyCount.length - 1; i > 0 ; i--) {
//计算所需当前纸币所需的张数
int c = money / moneyCount[i][0];
//如果需要的钱金额小于当前纸币面值,或者当前纸币数量不够
//用纸币数量和所需张数取最小完美契合了这个问题
c = Math.min(c,moneyCount[i][1]);
money -= c * moneyCount[i][0];
num += c;
}
if(money != 0){
//不能找到
return -1;
}else{
return num;
}
}
public static void main(String[] args) {
//存放纸币与数量: first:纸币,second:数量
int[][]arr = {{ 1, 3 }, { 2, 1 }, { 5, 4 }, { 10, 3 }, { 20, 0 }
,{50, 1}, { 100, 10 }};
Scanner scanner = new Scanner(System.in);
int money;
System.out.println("请输入要支付的钱");
money = scanner.nextInt();
int res = solve(money, arr);
if (res != -1)
System.out.println(res);
else
System.out.println("No");
}
}
结果:
多机调度问题
分析:题目意思很简单,机器是相同的意味着加工时间相同,独立作业说明所需时间不同.所以为了达到最短时间我们肯定首先想到的是把需要加工时间长的先加工,因为其所需时间可能贯穿整个加工时间.这也就是是贪心策略.
代码:
private static int findIndex(int[]arr){
int max = arr[0];
for(int i = 1 ; i < arr.length ; i++){
max = Math.max(arr[i],max);
}
return max;
}
private static int greedStrategy(int[] works, int[] machines){
Arrays.sort(works);
if(works.length <= machines.length){
return works[works.length-1];
}else{
//为每台机器安排工作并且先安排时间最长的
for(int i = works.length - 1 ; i >= 0 ; i--){
//初始化
int finish = 0;
int machineTime = machines[finish];
//找最先完成工作的机器并为其分配新的工作
for(int j = 1 ; j < machines.length ; j++){
if(machines[j] < machineTime){
machineTime = machines[j];
finish = j;
}
}
//将该机器工作时间更新,最后在所有机器的工作时间中找最大的即可
machines[finish] += works[i];
}
}
return findIndex(machines);
}
public static void main(String[] args) {
int n, m;
System.out.println("请输入作业数和机器数");
Scanner scanner = new Scanner(System.in);
n = scanner.nextInt();
m = scanner.nextInt();
int[] works = new int[n];
int[] machines = new int[m];
for (int i = 0; i < n; ++i)
works[i] = scanner.nextInt();
int x = greedStrategy(works, machines);
System.out.println(x);
}
结果:
活动选择
分析:活动持续时间有长有短,如果我们每次选择开始时间最早:
一个活动就占了所有的教室使用时间,因此不适合.
如果我们每次先选择持续时间最短的活动:
开始时间最早和持续时间最短都不能得到最优解,那么只有选择结束时间最早的活动了,如果是结束时间最早那么其实也包含了一个隐含条件就是开始时间也早.
按照这种选择,可以为未安排的活动留下尽可能多的时间.
那么有了这题的思路,我们来看下一题
无重叠区间(链接)
这题和上一题的其实是一样的,但上面看着会好理解一些.这题就是不能有重叠的区间,就像活动有开始和结束时间也不能重叠.有了上面的思路,这题很好解,贪心策略先选择重叠区间最小的一个.
代码:
class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
//lambda表达式按照数组 1 下标将重叠区间从小到大排列
Arrays.sort(intervals, (o1, o2) -> o1[1] - o2[1]);
int num = 1, i = 0;
for (int j = 1; j < intervals.length; j++)
{
//如果一个活动开始时间大于上一个活动结束时间,说明这个活动可以开始进行
if (intervals[j][0] >= intervals[i][1])
{
i = j;
num++;
}
}
return intervals.length - num;
}
}
总结:遇到某些题时,先思考是否有最优子结构,或者举例看是否满足,总之贪心算法在平时中用的较少,可以适时使用.