代码随想录训练营Day31 | Leetcode 455、376、53
一、455 分发饼干
题目链接:455 分发饼干
核心:贪心策略是用大尺寸饼干匹配大胃口孩子,这样能匹配最多的孩子。
首先需要对输入的两个数组:饼干尺寸数组和孩子胃口数组进行排序;
然后定义一个index从饼干尺寸数组的最后一个元素开始,逐个匹配孩子,需for循环遍历孩子胃口数组,也是从大胃口到小胃口,即从后往前;一旦正确匹配孩子,则index前移,直到遍历完所有孩子。
int findContentChildren(vector<int>& g, vector<int>& s) {
int res=0; //记录满足条件的孩子个数
//需要先排序才能用大尺寸饼干匹配大胃口孩子,或者小胃口孩子选择小尺寸饼干
sort(g.begin(),g.end());
sort(s.begin(),s.end());
int index=s.size()-1; //从大尺寸饼干开始往前遍历
for(int i=g.size()-1;i>=0;i--)
{//孩子
if(index>=0 && s[index]>=g[i]) //饼干
{//只有在饼干尺寸找到匹配胃口的孩子之后,才前移到上一个尺寸的饼干
res++;
index--;
}
}
return res;
}
二、376 摆动序列
题目链接:376 摆动序列
核心:贪心策略是删除(或不记录)单调坡度的节点(不包括单调坡度两端的节点),这样坡度就存在两个局部峰值。
存在峰值的情况:prediff<0 && curdiff>0 或者prediff>0 && curdiff<0,其中prediff和curdiff分别表示当前元素与前一个元素之差,和后一个元素与当前元素之差。
此外还存在其他特殊情况:
第一,上下坡之间有平坡:即prediff=0 && curdiff!=0或者prediff!=0 && curdiff=0的情况,这里采用前者,那么存在峰值的情况就为:prediff<=0 && curdiff>0 或者prediff>=0 && curdiff<0;
第二,数组首尾两端的处理:默认数组最右端有一个峰值,即令res初始化为1
第三,单调坡存在平坡:比如1,2,2,2,3,4,实际存在的峰值只有2个,因为整个数组都是单调的,实现代码时是通过prediff的更新,即prediff并非每一个节点都需要更新,而是在统计符合峰值的节点数时才更新prediff。
int wiggleMaxLength(vector<int>& nums) {
int res=1; //默认最后一个元素为峰值
int preDiff=0; //前一组之差,nums[i]-nums[i-1]
int curDiff=0; //当前组之差,nums[i+1]-nums[i]
for(int i=0;i<nums.size()-1;++i)
{//遍历数组元素,从0-len-2
curDiff=nums[i+1]-nums[i];
if((preDiff>=0 && curDiff<0) || (preDiff<=0 && curDiff>0))
{//符合峰值、峰谷的要求
res++;
preDiff=curDiff; //更新前一组元素之差
}
}
return res;
}
三、53 最大子数组和
题目链接:53 最大子数组和
核心:贪心策略是当前区间元素和(上一个子数组+当前元素之和)为负数时,则舍弃当前元素及之前元素的子数组,从当前元素的下一个开始重新计算子数组和count;一旦子数组和count大于此前所记录的最大子数组和res时,则更新res,最终返回的最大子数组和即为res。
注意:res初始化为INT_MIN,因为如果所有元素均为负数,那么最大子数组和也为负数,此时若res初始化为0,则会出现bug。
int maxSubArray(vector<int>& nums) {
int res=INT_MIN; //记录最大子数组和,需设置为最小值,可能存在nums全为负数的情况
int count=0; //记录当前区间的数组和
for(int i=0;i<nums.size();++i)
{//遍历数组元素
count+=nums[i];
if(count>res)
res=count; //与记录的区间最大值比较,保留区间的最大值
if(count<=0)
count=0; //一旦联系和为负数,则从下一个元素开始重新计算区间和
}
return res;
}