贪心算法——分糖果
题目一.分糖果
已知一些孩子和一些糖果,每个孩子有需求因子g,每个糖果有大小s,当某个糖果的大小s>= 某个孩子的需求因子g时,代表该糖果可以满足该孩子;求使用这些糖果,最多能满足多少孩子?(注意,某个孩子最多只能用1个糖果满足)
例如,需求因子数组g=【5,10,2,9,15,9】;糖果大小数组s=【6,1,20,3,8】;最多可以满足3个孩子。
class Solution {
public: //孩子们的需求因子g数组
int findContentChildren(std::vector<int>&g,std::vector<int>& s)
{ //糖果的大小 s数组
} //返回最多可以有多少孩子被满足};
};
(选自 LeetCode 455. Assign Cookies)
分析:
例如,需求因子数组g=【5,10,2,9,15,9】;糖果大小数组s=【6,1,20,3,8】。为了更明显的判断某个孩子可以被某个糖果满足,对g,s进行排序后观察∶
g=[2,5,9,9,10,15];s=[1,3,6,8,20]。
1.是否可以直接暴力枚举,对每个糖果都尝试是否可以满足某个孩子?
2.当某个孩子可以被多个糖果满足时,是否需要优先用某个糖果满足这个孩子?
3.当某个糖果可以满足多个孩子时,是否需要优先满足某个孩子?
贪心规律:
需求因子数组g=【2.5,9,9,10,15】;糖果大小数组s=【,3,6.8.20】。核心目标∶让更多孩子得到满足,有如下规律∶
1.某个糖果如果不能满足某个孩子,则该糖果也—定不能满足需求因子更大的孩子。如,
糖果1(s= 1)不能满足孩子1(g=2),则不能满足孩子2、孩子3、、孩子7;糖果2(s=3)不能满足孩子2(g=5),则不能满足孩子3、孩子4、…、孩子7;
2.某个孩子可以用更小的糖果满足,则没必要用更大糖果满足,因为可以保留更大的糖果满足需求因子更大的孩子。(贪心!)如,
孩子1(g=2),可以被糖果2(s=3)满足,则没必要用糖果3、糖果4、糖果5满足;孩子2(g=5),可以被糖果3(s= 6)满足,则没必要用糖果4、糖果5满足;
3.孩子的需求因子更小则其更容易被满足,故优先从需求因子小的孩子尝试,用某个糖果满足一个较大需求因子的孩子或满足一个较小需求因子的孩子效果是—样的(最终满足的总量不变).(贪心!)
算法思路:
1.对需求因子数组g与糖果大小数组S进行从小到大的排序。
2.按照从小到大的顺序使用各糖果尝试是否可满足某个孩子,每个糖果只尝试1次;若尝试成功,则换下一个孩子尝试;直到发现没更多的孩子或者没更多的糖果,循环结束。
算法实现:
#include <vector>
#include <algorithm>
class Solution {
public:
int findContentChildren(std::vector<int>&g,std::vector<int>& s){
std::sort (g.begin (),g.end()); //对孩子的需求因子g与糖果大小s两数组排序
std::sort (s.begin (),s.end());
int child = 0;
int cookie_=_6; //hild代表已满足了几个孩子,cookie代表尝试了几个糖果
while(child<g.size()&&cookie<s.szie(){ //当孩子或糖果同时均未尝试完时
if (g[chi1d] <= s[cookie]){ //当孩子孩子的满足因子小于或等于糖果大小时
child++; //该糖果满足了孩子,孩子指针child向后移动
}
Cookie++; //无论成功或失败,每个糖果只尝试一次,cookie向后移动
}
return child; //最终child即为得到满足的孩子的个数
}
} ;
]