贪心算法
贪心算法的思想就是在局部的当前步做出最优的决定,最后得到全局的最优决定。
- 贪心算法是最自然智慧的算法。
- 贪心算法用一种最功利的标准,总是做出在当前看来是最好的选择。
- 贪心算法的难点在于怎么证明局部最 功利的标准可以得到全局最优解。
- 对于贪心算法的学习主要以增加阅历和经验为主。
通俗的来讲,贪心算法就好比一个人做事情,做事情的时候很是贪心,事情的每一步都要得到最优的决定来使自己的最终的利益也会是最大化。
下面两道题是用贪心思想求解。
题目1:字符串拼接
给定一个由字符串组成的数组strs,
必须把所有的字符串拼接起来,
返回所有可能的拼接结果中,字典序最小的结果。
解决这道题目首先我们要知道什么叫字典序
字典序:在数学中,字典或词典顺序(也称为词汇顺序,字典顺序,字母顺序或词典顺序)是基于字母顺序排列的单词按字
母顺序排列的方法。 这种泛化主要在于定义有序完全有序集合(通常称为字母表)的元素的序列(通常称为计算机科学中的
单词)的总顺序。
eg:对于数字1、2、3…n的排列,不同排列的先后关系是从左到右逐个比较对应的数字的先后来决定的。例如对于5个数字的排
列 12354和12345,排列12345在前,排列12354在后。按照这样的规定,5个数字的所有的排列中最前面的是12345,最后面的
是 54321。字符也一样,例如abc排列在abk前、ac排列在b前。
怎样做到拼接起来最后的字符串字典序最小呢?
采用贪心的思想,局部每两个字符串拼接的时候都让拼接的结果的字典序最小,从每一步得到最终的最小的字典序拼接。
那怎样才能让局部每两个字符串拼接的时候都让拼接的结果的字典序最小呢?
- 第一种贪心策略
X字典序<=Y字典序,X排在前,否则Y排在前。
这种贪心策略可以轻易举出来反例–>[b,ba],所以这种策略不正确.
- 第二种贪心策略
XY字典序<=YX字典序,X排在前,否则Y排在前。
第二种策略需要证明这种排序具有传递性,贪心策略才成立。
最后证明出第二种贪心策略是成立的(证明略)。
代码如下:
//比较器,定义字符串数组怎么进行比较排序
public static class MyComparator implements Comparator<String> {
@Override
public int compare(String a, String b) {
return (a + b).compareTo(b + a);
}
}
//主函数
public static String lowestString(String[] strs) {
if (strs == null || strs.length == 0) {
return "";
}
Arrays.sort(strs, new MyComparator());
String path = "";
for (int i = 0; i < strs.length; i++) {
path += strs[i];
}
return path;
}
题目二:安排会议议程
一些项目要占用一个会议室宣讲,会议室不能同时容纳两个项目的宣讲。
给你每一个项目开始的时间和结束的时间
你来安排宣讲的日程,要求会议室进行的宣讲的场次最多,返回最多的宣讲场次。
贪心策略:结束时间最早的会议安排到最前面,接下来安排会议结束时间第二早的会议 … 每一步都安排在当前看来结束时间最早的会议,最后就可以得到最多的宣讲场次。
代码如下:
//定义一个根据结束时间进行升序排序的比较器
public static class ProgramComparator implements Comparator<Program> {
@Override
public int compare(Program o1, Program o2) {
return o1.end- o2.end;
}
}
//主函数
public static int beatArrange2(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;
}