贪心算法
贪心算法或贪心思想采用贪心的策略,保证每次操作都是局部最优的,从而使最后得到的结果是全局最优的。
455 分发饼干
题目表述
(简单)
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。
对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。
比如:你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。所以你应该输出1。
题解:
class Solution {
public:
int findContentChildren(vector<int>& g, vector<int>& s) {
// 首先将孩子的胃口与饼干尺寸都按照从小到大进行排序
sort(g.begin(), g.end());
sort(s.begin(), s.end());
// 定义初始值
int child = 0;
int cookie = 0;
// 从小到大开始遍历,使用较小的饼干优先满足胃口较小的孩子
// 如果
while(child < g.size() && cookie < s.size()) {
if(g[child] <= s[cookie]) ++child;
++cookie;
}
return child;
}
};
435 无重叠区间
题目表述
(中等)
给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。
注意:
可以认为区间的终点总是大于它的起点。
区间 [1,2] 和 [2,3] 的边界相互“接触”,但没有相互重叠。
题解
class Solution {
public:
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
// 如果输入为空则返回空
if (intervals.empty()){
return 0;
}
int n = intervals.size();
// 对输入的区间进行排序,排序方式为按照区间右边从小到大进行排序
// 使用Lambda方式定义排序方式
// Lambda 表达式的定义形式为[外部变量访问方式说明符] (参数表) -> 返回值类型{语句块}
sort(intervals.begin(), intervals.end(), [](vector<int>& a, vector<int>& b){
return a[1]<b[1];
});
// 定义初始值,初始化为第一个区间
int total = 0, prev = intervals[0][1];
// 进行遍历,如果后一个区间的左值小于前一个区间的右值,则需要去除,否则将更新prev
for (int i = 1; i<n; i++){
if(intervals[i][0] < prev){
total++;
}else{
prev = intervals[i][1];
}
}
return total;
}
};
135 分发糖果
题目描述
(困难)
老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。
你需要按照以下要求,帮助老师给这些孩子分发糖果:
每个孩子至少分配到 1 个糖果。
评分更高的孩子必须比他两侧的邻位孩子获得更多的糖果。
那么这样下来,老师至少需要准备多少颗糖果呢?
题解
把所有孩子的糖果数初始化为 1;先从左往右遍历一遍,如果右边孩子的评分比左边的高,则右边孩子的糖果数更新为左边孩子的糖果数加 1;再从右往左遍历一遍,如果左边孩子的评分比右边的高,且左边孩子当前的糖果数不大于右边孩子的糖果数,则左边孩子的糖果数更新为右边孩子的糖果数加 1。
class Solution {
public:
int candy(vector<int>& ratings) {
// 只有一个孩子即返回一个
int size = ratings.size();
if(size < 2){
return size;
}
// 初始化为长度为size,值为1的数组
vector<int> num(size, 1);
// 从左往右遍历,如果右边孩子的评分比左边的高,则右边孩子的糖果数更新为左边孩子的糖果数加1
for(int i = 1; i < size; i++){
if(ratings[i] > ratings[i-1]){
num[i] = num[i-1] + 1;
}
}
// 从右往左遍历,如果左边孩子的评分比右边的高,且左边孩子当前的糖果数不大于右边孩子的糖果数,
// 则左边孩子的糖果数更新为右边孩子的糖果数加1
for(int i = size - 1; i > 0; i--){
if(ratings[i] < ratings[i-1]){
// 直接返回左边孩子当前的糖果数与右边孩子的糖果数加1的最大值
num[i-1] = max(num[i-1], num[i] + 1);
// num[i] = num[i-1] + 1;
}
}
// 对数组所有的元素进行相加得出结果
return accumulate(num.begin(), num.end(), 0);
//accumulate定义在#include<numeric>,第三个参数是初值
}
};