代码随想录算法训练营
Day27 代码随想录算法训练营第27 天 |LeetCode455.分发饼干 LeetCode376. 摆动序列 LeetCode53. 最大子序和
目录
前言
LeetCode455.分发饼干
LeetCode376. 摆动序列
LeetCode53. 最大子序和
一、基础
1、贪心算法的本质:
每一阶段的局部最优叠加在一起就是全局最优
2、何时使用贪心:
举不出反例就可以用贪心
3、步骤
分成子问题
贪心策略
求解子问题
局部最优叠加
二、LeetCode455.分发饼干
1.题目链接
2.思路
(1)怎样能让更多的小孩有饼干吃------优先把大饼干分配给胃口大的小孩
(2)用i表示小孩胃口,j表示饼干
1)下标的更新规则:
① 从后向前遍历:i从g.size()-1开始,j从s.size()-1开始,
② 饼干被吃了需要j–,小孩确定是否得到饼干后i–
2)为什么小孩是外层循环
如果最大的胃口最大的小孩不能被最大的饼干满足,我们会换一个小孩讨论而不是换一个饼干
3.题解
lass Solution {
public:
int findContentChildren(vector<int>& g, vector<int>& s) {
sort(g.begin(), g.end());
sort(s.begin(), s.end());
int sum = 0;
int j = s.size() - 1;
for (int i = g.size() - 1; i >= 0; i--) {
if (j >= 0 && s[j] >= g[i]) {
sum++;
j--;
}
}
return sum;
}
};
三、LeetCode376. 摆动序列
1.题目链接
2.思路
(1)思路
1)获取摆动子序列需要删掉中间点,保留极大值点和极小值点。想要摆动子序列最大,就需要保存所有极值点
因此,极值点的数量为答案
2)极值点判定
pre=nums[i]-nums[i-1] cur=nums[i+1]-nums[i]
pre>0&&cur<0 极大值
pre<0&&cur>0 极小值
(2)特殊情况
1)左端点处理:由于cur=nums[i+1]-nums[i],左端点的cur难以求解,我们默认左端点为极值点
2)上下坡中间有平坡:
①极值判定条件改为
pre>=0&&cur<0 极大值
pre<=0&&cur>0 极小值
②为什么不是 cur>=0 cur<=0:因为左端默认是极值点
e.g[3,2,2]
这种情况答案为2,第二个2因为是左端,算作极值点,第一个2必须删掉,所以对极值点的判定不包括cur=0
③单调坡度有平坡
e.g [1,2,2,2,3]
按照每次遍历都更新pre,第三个2会被看作极值点(pre=0 cur>0)
所以平坡内部不应该更新pre,而是应该保持进入平坡之前的Pre
3.题解
class Solution {
public:
int wiggleMaxLength(vector<int>& nums) {
int res = 1;
int pre = 0;
int cur = 0;
for (int i = 0; i < nums.size() - 1; i++) {
cur = nums[i + 1] - nums[i];
if ((cur > 0 && pre <= 0) || (cur < 0 && pre >= 0)) {
res++;
pre = cur;
}
}
return res;
}
};
四、LeetCode53. 最大子序和
1.题目链接
2.思路
(1)贪心思路:
如果此时的子序列和为负,那么清零:因为(当前和+下一个元素)<下一个元素
这个操作相当于修改子序列的起点,将前面的子序列作废,重新计算子序列
(2)dp思路
dp数组:dp[i-1]表示遍历到下标i的元素时,前面子序列的长度
如果dp[i-1]小于0,那么前面的子序列作废,从i开始计算新的子列,dp[i]=nums[i]
3.题解
贪心
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int res = -100000;
int sub = 0;
for (int i = 0; i < nums.size(); i++) {
sub += nums[i];
if (sub > res)
res = sub;
if (sub < 0)
sub = 0;
}
return res;
}
};
dp
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int res = -100000;
vector<int> dp;
for (int i = 0; i < nums.size(); i++) {
dp.push_back(0);
}
for (int i = 0; i < nums.size(); i++) {
if (i == 0)
dp[i] = nums[i];
else if (dp[i - 1] < 0)
dp[i] = nums[i];
else
dp[i] = dp[i - 1] + nums[i];
if (res < dp[i])
res = dp[i];
}
return res;
}
};