今天是学习算法的第一天,以后每天都会坚持学习一个算法,当然是要学懂学会,而不是浅尝辄止.每一个学会的算法都会记录下来,以方便后面复习查阅.
贪心算法有很多经典的应用,比如霍夫曼编码(Huffman Coding)、Prim 和 Kruskal 最小生成树算法、还有 Dijkstra 单源最短路径算法。
1 什么是贪心算法
所谓贪心算法是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,它所做出的仅仅是在某种意义上的局部最优解。
贪心算法没有固定的算法框架,算法设计的关键是贪心策略的选择。必须注意的是,贪心算法不是对所有问题都能得到整体最优解,选择的贪心策略必须具备无后效性(即某个状态以后的过程不会影响以前的状态,只与当前状态有关。)
贪心算法可以简单描述为:大事化小,小事化了。对于一个较大的问题,通过找到与子问题的重叠,把复杂的问题划分为多个小问题。并且对于每个子问题的解进行选择,找出最优值,进行处理,再找出最优值,再处理。也就是说贪心算法是一种在每一步选择中都采取在当前状态下最好或最优的选择,从而希望得到结果是最好或最优的算法。
所以,对所采用的贪心策略一定要仔细分析其是否满足无后效性。
2 基本思路
- 建立数学模型来描述问题。
- 把求解的问题分成若干个子问题。
- 对每一子问题求解,得到子问题的局部最优解。
- 把子问题的局部最优解合成原来问题的一个解。
3 适用问题
问题的求解可以由一系列的决策步骤构成,每步决策依赖于某种局部最优的贪心策略。正确的贪心策略要保证每一步基于局部优化性质的选择最终导致全局的最优解。如果不具有上述性质,贪心法对某些实例只能得到近似解。
贪心策略适用的前提是局部最优策略能导致产生全局最优解。
4 案例
钱币找零问题
这是生活中很常见的问题,你的钱包中有1元,5元,10元,50元,100元,分别为a1张,a2张,a3张,a4张,a5张,你需要用这些钱去支付y元,至少需要多少张纸币.贪心算法来计算的话,很明显,每一次用最大面额的纸钞即可.
public static int payMoney(int money){
int n = 5;
//定义钱数与张数
int count[] = {5,3,3,4,10};
int value[] = {1,5,10,50,100};
int num = 0;
for (int i = n - 1;i >= 0;i--){
int c = Math.min(money / value[i], count[i]);
money = money - c*value[i];
num += c;
}
return num;
}
LeetCode 455.Assign Cookies
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i ,都有一个胃口值 gi ,这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j ,都有一个尺寸 sj 。如果 sj >= gi ,我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。
示例 1:
输入: [1,2,3], [1,1]
输出: 1
解释:
你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。
虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。
所以你应该输出1。
示例 2:
输入: [1,2], [1,2,3]
输出: 2
解释:
你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。
你拥有的饼干数量和尺寸都足以让所有孩子满足。
所以你应该输出2.
这里贪心就是用最小数量的饼干满足孩子的需求,这样大饼干就可以用来满足需求大的孩子.因为需求小的孩子是最好满足的,所以需要先进行一下排序再分配.
public static int distributeCookies(int[] ch,int[] co){
Arrays.sort(ch);
Arrays.sort(co);
int gi = 0;
int sj = 0;
while (sj <= co.length & gi <= ch.length){
if (ch[gi] <= co[sj]){
gi++;
}
sj++;
}
return gi;
}
共同学习,写下你的评论
评论加载中...
作者其他优质文章