贪心算法是一种常见的算法思想,其特点就是通过每次都选择局部最优来达到实现全局最优的目的。
例如让你从一堆钞票中拿走10张,你为了达到拿到最大金额的目的,必定会每次都拿走最大面额的钞票,这就是贪心算法的思想。本博客是记录作者做贪心算法的较困难的题的笔记。
一、贪心算法的权衡问题
LeetCode题目 | 相关题目类型 | 题目类型分析 | 题目思路 | 相关链接 |
---|---|---|---|---|
135 | 分发糖果(困难难度) | https://leetcode-cn.com/problems/candy/ | ||
406 | 根据身高重建队列(中等难度) | 根据两个维度给数组排序 | 按照身高从高到低排序,然后根据k维度进行插入 | https://leetcode-cn.com/problems/queue-reconstruction-by-height/ |
406 根据身高重建队列
本题有两个维度,h和k,看到这种题目一定要想如何确定一个维度,然后在按照另一个维度重新排列。
按照身高h来排序呢,身高一定是从大到小排(身高相同的话则k小的站前面),让高个子在前面。
那么只需要按照k为下标重新插入队列就可以了,为什么呢?
以图中{5,2} 为例:
代码如下:
static bool cmp(vector<int> &a,vector<int> &b){
if(a[0]==b[0])// 如果身高相同则按照k从小到大排列
{
return a[1]<b[1];
}
return a[0]>b[0];//默认将身高按照从大到小排列
}
vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
/*输入一个二维数组,输出一个二维数组*/
sort(people.begin(),people.end(),cmp);
vector<vector<int>> que;
// 按照k调整队列
for (int i = 0; i < people.size(); i++) {
int position = people[i][1];
que.insert(que.begin() + position, people[i]);
}
return que;
}
按照身高排序之后,优先按身高高的people的k来插入,后序插入节点也不会影响前面已经插入的节点,最终按照k的规则完成了队列。
但使用vector是非常费时的,C++中vector(可以理解是一个动态数组,底层是普通数组实现的)如果插入元素大于预先普通数组大小,vector底部会有一个扩容的操作,即申请两倍于原先普通数组的大小,然后把数据拷贝到另一个更大的数组上。
所以使用vector(动态数组)来insert,是费时的
二、贪心算法的树题目
LeetCode题目 | 相关题目类型 | 题目类型分析 | 题目思路 | 相关链接 |
---|---|---|---|---|
968 | 监控二叉树(困难难度) | https://leetcode-cn.com/problems/binary-tree-cameras/ | ||
968 监控二叉树
代码如下: