「这是我参与2022首次更文挑战的第35天,活动详情查看:2022首次更文挑战」。
一、字典序最小的结果
给定一个由字符串组成的数组strs,必须把所有的字符串拼接起来,返回所有可能的拼接结果中,字典序最小的结果
1、分析
arr = {"b", "ba"}
- 先拼b,后拼ba,则结果是bba
- 先拼ba,后拼b,则结果是bab
- 字典序最小的结果是bab
贪心:如果x.y < y.x,x前,否则y前
贪心的解法:排序(比较器)
2、实现
public static class MyComparator implements Comparator<String> {
@Override
public int compare(String a, String b) {
return (a + b).compareTo(b + a);
}
}
// 贪心解
public static String lowestString2(String[] strs) {
if (strs == null || strs.length == 0) {
return "";
}
Arrays.sort(strs, new MyComparator());
String res = "";
for (int i = 0; i < strs.length; i++) {
res += strs[i];
}
return res;
}
二、最多会议室宣讲场次
一些项目要占用一个会议室宣讲,会议室不能同时容纳两个项目的宣讲。
给你每一个项目开始的时间和结束的时间,
你来安排宣讲的日程,要求会议室进行的宣讲的场次最多。
返回最多的宣讲场次。
1、分析
贪心的核心思路:
所有会议的结束时间从小到大排序,定义会议的结束时间为timeLine,遍历每个会议,每个会议的开始时间只要大于等于timeLine,就可以安排,当前的timeLine来到当前会议的结束时间
2、实现
public static int bestArrange2(Program[] programs) {
Arrays.sort(programs, new ProgramComparator());
int timeLine = 0;
int result = 0;
// 依次遍历每一个会议,结束时间早的会议先遍历
for (int i = 0; i < programs.length; i++) {
if (timeLine <= programs[i].start) {
result++;
timeLine = programs[i].end;
}
}
return result;
}
public static class ProgramComparator implements Comparator<Program> {
@Override
public int compare(Program o1, Program o2) {
return o1.end - o2.end;
}
}
三、金条分割的最小代价
一块金条切成两半,是需要花费和长度数值一样的铜板的。
比如长度为20的金条,不管怎么切,都要花费20个铜板。 一群人想整分整块金条,怎么分最省铜板?
例如,给定数组{10,20,30},代表一共三个人,整块金条长度为60,金条要分成10,20,30三个部分。
如果先把长度60的金条分成10和50,花费60; 再把长度50的金条分成20和30,花费50;一共花费110铜板。
但如果先把长度60的金条分成30和30,花费60;再把长度30金条分成10和20, 花费30;一共花费90铜板。
输入一个数组,返回分割的最小代价。
1、分析
arr = {2, 1, 7, 3, 4, 2, 1} 金条长度为20
贪心策略:小根堆
准备一个小根堆,依次放进去
每次从小根堆里弹出两个数,两个数合成一个数(加起来)再让进去,周而复始,小根堆里只存在一个数的时候停,整个过程(这棵树)就是金条最小代价的分割方法,此过程就是著名的赫夫曼编码
金条最优的划分代价就是所有画圈的加起来 = 20 + 8 + 12 + 4 + 5 + 2 = 51
2、实现
public static int lessMoney(int[] arr) {
PriorityQueue<Integer> pQ = new PriorityQueue<>();
for (int i = 0; i < arr.length; i++) {
pQ.add(arr[i]);
}
int sum = 0;
int cur = 0;
while (pQ.size() > 1) {
cur = pQ.poll() + pQ.poll();
sum += cur;
pQ.add(cur);
}
return sum;
}
四、总结
贪心算法解题常常用到排序、堆来实现
贪心算法不要证明,贪心的本质就是每个策略都是最好的,通过对数器进行验证即可
贪心策略有时候不一定就贪的对