力扣刷题之贪心算法(C++)
Posted 哈喽喔德
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了力扣刷题之贪心算法(C++)相关的知识,希望对你有一定的参考价值。
(学习参考书:LeetCode101)
贪心算法
贪心算法采用贪心的策略,保证每次操作都是局部最优的,从而使最后得到是全局最优的。
解题步骤:
- 将问题分解为若干个子问题,寻找合适的贪心策略
- 求解每一个子集的最优解
- 将局部最优解迭代成全局最优解
力扣例题
455.分发饼干
分析:
因为饥饿度最小的孩子最容易吃饱,所以优先考虑这个孩子。为了使剩下的饼干尽可能的满足饥饿度更大的孩子,所以应该把大于等于这个孩子饥饿度的且最小的饼干给这个孩子。然后采取同样的策略,直到没有满足的饼干为止。
题解:
class Solution {
public:
int findContentChildren(vector<int>& g, vector<int>& s) {
//将饼干和孩子从小到大排序
sort(g.begin(),g.end());
sort(s.begin(),s.end());
//初始化辅助变量
int cnt = 0;
int j = 0;
//循环至一方没有剩余
while(cnt<g.size()&&j<s.size()){
//当孩子能吃饱时,同时++进行下一组比对
//当孩子不能吃饱时,这个孩子继续和下一个饼干匹配
if(g[cnt]<=s[j]){
++cnt;
}
++j;
}
return cnt;
}
};
135.分发糖果
分析:
只需要两次遍历,把所有孩子糖果数初始化为1;先从左到右遍历一遍,如果右边孩子的评分比左边的高,则右边更新为左边的糖果数+1;再从右往左遍历,如果左边的右边高,且左边孩子的糖果数不大于右边孩子的糖果数,则左边更新为右边的+1。
题解:
class Solution {
public:
int candy(vector<int>& ratings) {
int size = ratings.size();
//如果只有一个孩子返回1即可
if(size==1){
return size;
}
//创建一个数组,表示每个孩子对应的糖果数,初始值都为1
vector<int> v(size,1);
//从左往右遍历
for(int i=1;i<size;++i){
if(ratings[i-1]<ratings[i]){
v[i] = v[i-1]+1;
}
}
//从右往左遍历
for(int i=size-1;i>0;--i){
if(ratings[i-1]>ratings[i]){
//需要判断是否左边已经大于右边
v[i-1] = max(v[i-1],v[i]+1);
}
}
//求和得出需要的总糖果数
return accumulate(v.begin(),v.end(),0);
}
};
435.无重叠区间
分析:
选择的区间结尾越小,余留给其他区间的空间就越大,就能保留更多的区间。因此采取的贪心策略是,优先保留结尾笑且不相交的区间。先把区间按照结尾大小排序,每次选择结尾最小且与前一个选择的区间不重叠的区间。
题解:
class Solution {
public:
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
//无区间直接返回0
if(intervals.empty()){
return 0;
}
//使用自定义规则的sort函数对区间按照结尾大小排序
//这里定义规则的vector<int> a用法没错,但是在力扣上超时
//应该替换为const auto& a
sort(intervals.begin(),intervals.end(),
[](vector<int> a,vector<int> b){
return a[1]<b[1];
});
int cnt = 0;//计数器
int start = intervals[0][1];//初始设置为第一个区间的结尾
for(int i=1;i<intervals.size();++i){
if(intervals[i][0]<start){
//当下一个区间的开始与上一个区间的结尾重合时,应该删除该区间
++cnt;
}
else{
//当不重合时,更新需要比较的区间的结尾
start = intervals[i][1];
}
}
return cnt;
}
};
以上是关于力扣刷题之贪心算法(C++)的主要内容,如果未能解决你的问题,请参考以下文章