前段时间回溯法,DFS,BFS做的差不多了,今天开始尝试四大算法中的贪心算法;
四大算法是哪四大?
- 贪心算法
- 分而治之算法(递归)
- 动态规划
- 穷举法
据说百分之95的算法问题都可以归类属于它们;
假设一个问题比较复杂,暂时找不到全局最优解,那么我们可以考虑把原问题拆成几个小问题(分而治之思想),分别求每个小问题的最优解,再把这些“局部最优解”叠起来,就“当作”整个问题的最优解了。
贪心算法就是在当前没有办法找到全局最优解的情况下,去追求目前能达到的局部最优解;
最经典的例子就是01背包问题;
一个背包只能装xxx重量的物品,现在有xxx个物品,每个物品的价值分别是xxx,让你找个方案让背包能装下最大价值的物品;
那么可以想出3个贪心装法:
- 按价值的大小排序物品,分别装入,每次装价值最大的
- 按重量的大小排序物品,分别装入,每次装最轻量的
- 按价值密度大小排序物品,分别装入
很显然价值密度是更好的方案;
因此可以看出,贪心算法并不一定能得到问题的最优解,还有选择好适当的贪心方案;
总结一下使用贪心算法的前提:
1、原问题复杂度过高;
2、求全局最优解的数学模型难以建立;
3、求全局最优解的计算量过大;
4、没有太大必要一定要求出全局最优解,“比较优”就可以。
再来看一下leetcode这题:
对于胃口小的孩子,我们当然是尽量给他同等大小的饼干,因此需要将饼干和孩子都从小到大排序;我们的贪心是每次都争取喂饱当前的小孩;从头开始拿每个小饼干去和孩子比较,要是大于等于孩子的胃口,那么喂饱的孩子+1;要是小于孩子的胃口,就往后找饼干直到找到能满足孩子胃口的饼干
class Solution {
public:
int findContentChildren(vector<int>& g, vector<int>& s) {
sort(g.begin(),g.end());
sort(s.begin(),s.end());
int res=0;
int pos = 0;
for(int i=0;i<g.size();i++)
{
for(int j=pos;j<s.size();)
{
if(g[i]>s[j])
//当前的饼干无法满足当前的小孩
{
j++;
}
else
//当前的饼干可以满足当前的小孩
{
res++;
pos = ++j;
break;
}
pos = j;
}
}
return res;
}
};
但是效率感人。。。
看了看评论,据说自己写排序算法会快一点。。