Leetcode101 贪心算法

141 阅读3分钟

8.16 贪心算法

顾名思义,贪心算法或贪心思想采用贪心的策略,保证每次操作都是局部最优的,从而使最后得到的结果是全局最优的。

(1)455. Assign Cookies (Easy)

题目描述

有一群孩子和一堆饼干,每个孩子有一个饥饿度,每个饼干都有一个大小。每个孩子只能吃最多一个饼干,且只有饼干的大小大于孩子的饥饿度时,这个孩子才能吃饱。求解最多有多少孩子可以吃饱。

本人思路

这个题目比较简单,很容易想到就是先排序,然后依次对仗即可。

(2)135. Candy (Hard)

题目描述

一群孩子站成一排,每一个孩子有自己的评分。现在需要给这些孩子发糖果,规则是如果一个孩子的评分比自己身旁的一个孩子要高,那么这个孩子就必须得到比身旁孩子更多的糖果;所有孩子至少要有一个糖果。求解最少需要多少个糖果。

本人思路

首先可以想到的是,一定是从最小的评分开始入手,然后依次递推。因此,可以先对所有的评分进行排序,然后利用find和distance函数进行依次查找,并根据左右两边的评分数对当前的孩子糖果数进行赋值(此时需要注意边界条件)。遍历完后将所有的糖果数相加即可。这种思路比较简单,但是效果不是很好。并且在做题时没注意个数为0的边界条件。

题解思路

做完了题目 455,你会不会认为存在比较关系的贪心策略一定需要排序或是选择?虽然这一道题也是运用贪心策略,但我们只需要简单的两次遍历即可:把所有孩子的糖果数初始化为 1;先从左往右遍历一遍,如果右边孩子的评分比左边的高,则右边孩子的糖果数更新为左边孩子的糖果数加 1;再从右往左遍历一遍,如果左边孩子的评分比右边的高,且左边孩子当前的糖果数不大于右边孩子的糖果数,则左边孩子的糖果数更新为右边孩子的糖果数加 1。

通过这两次遍历,分配的糖果就可以满足题目要求了。这里的贪心策略即为,在每次遍历中,只考虑并更新相邻一侧的大小关系。

在样例[1,0,2]中,我们初始化糖果分配为 [1,1,1],第一次遍历更新后的结果为 [1,1,2],第二次遍历更新后的结果为 [2,1,2]。

(3)435. Non-overlapping Intervals (Medium)

题目描述

给定多个区间,计算让这些区间互不重叠所需要移除区间的最少个数。起止相连不算重叠。

本人思路

在做这个题目的时候就想到了在算法课程上学到的安排演出时间,仔细思考了一下发现有异曲同工之妙。安排演出的时候是需要安排的数目最多,这里是移除的区间数目最少,因此,都是先将数据按照数据结尾大小排序,如果开始值能≥上一个的结束值即可。

不过需要注意的是,由于std中没有对应的sort函数,因此需要使用c++的Lambda对sort进行自定义排序,结构为:

sort(intervals.begin(), intervals.end(), [](vector<int> a, vector<int> b) {
		return a[1] < b[1];
});

总结

今天的题目总的来说比较简单,基本上都靠自己所想的思路做出来了。但由于确实很久没有接触过c++了,很多语法都不熟练,还需要查找相应函数的用法。继续加油!