本文将给出贪心算法的最基本问题:给小朋友们分配饼干
问题的具体描述如下:
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。
来源:力扣(LeetCode)455
链接:https://leetcode.cn/problems/assign-cookies
贪心算法的基本思想就是选择每一阶段的局部最优,以达到全局最优,在考虑问题的某一个阶段时,不必考虑下一个阶段的状态,只需让当前状态达到最优解。
在本题中,为了使满足小孩子的数量最多,就要尽可能的充分利用饼干,以避免造成饼干的浪费,更大的饼干既可以满足胃口大的孩子,又可以满足胃口小的孩子,因此为了避免浪费,让其优先满足胃口大的孩子,因此,局部最优原理在此体现为用饼干尽可能喂给胃口大的孩子,全局最优体现为尽可能满足数量越多的孩子,因此,此题可以用贪心算法解决。
具体解决办法
- 先对两个数组,即孩子的胃口数组和饼干数组进行从大到小排序,本文采用库函数中的快速排序函数,具体如下:
void qsort(void*base, size_t num, size_t width,int(cdecl*cmp)(const void*eleml,const void*elem2)
其中:base表示数组的首地址
num表示数组大小
width表示数组中每个元素的大小
cmp是自己定义的比较函数
比较函数代码如下:
int cmp(const void* p1, const void* p2)//快速排序中的回调函数
{
return (*(int*)p2 - *(int*)p1);//从大往小排序
}
- 然后从前向后遍历孩子的胃口数组,用大饼干首先满足胃口大的孩子 ,并设置num来记录满足的小孩子的数量
全部代码如下
//2023.04.05小昂洋白菜
int cmp(const void* p1, const void* p2)//快速排序中的回调函数
{
return (*(int*)p2 - *(int*)p1);//从大往小排序
}
int findContentChildren(int* g, int gSize, int* s, int sSize) {//g是饼干,s是孩子
//首先调用快速排序的库函数
int num = 0;
qsort(g, gSize, sizeof(int), cmp);//孩子
qsort(s, sSize, sizeof(int), cmp);//饼干
int i = 0, j = 0;
for (int i = 0; i < gSize; i++)//孩子
{
if (j < sSize && s[j] >= g[i])//饼干
{
num++;
j++;
}
}
return num;
}
其中for控制的是外层孩子胃口的循环,内层的if控制的是饼干,如果将二者的顺序进行调换则不能正常运行,具体如下:
这种情况下 s数组中的7,6,3,2,2依次去匹配g数组中的8 都不能满足,得到的最终结果是0,是错误的。