理论基础
贪心算法其实就是没有什么规律可言
贪心的本质是选择每一阶段的局部最优,从而达到全局最优。
贪心算法并没有固定的套路
最好用的策略就是举反例,如果想不到反例,那么就试一试贪心吧。
刷题或者面试的时候,手动模拟一下感觉可以局部最优推出整体最优,而且想不到反例,那么就试一试贪心。
贪心一般解题步骤:分为如下四步:
- 将问题分解为若干个子问题
- 找出适合的贪心策略
- 求解每一个子问题的最优解
- 将局部最优解堆叠成全局最优解
贪心没有套路,说白了就是常识性推导加上举反例
455.分发饼干
思路:用小饼干尽量先去满足胃口小的孩子,或者用大饼干尽量先去满足胃口大的孩子
对孩子的胃口,和饼干进行排序
遍历的时候,一定是先遍历孩子,再遍历饼干,因为如果饼干不能满足条件的话,是不能一直 减减的
class Solution {
public:
int findContentChildren(vector<int>& g, vector<int>& s) {
sort(g.begin(), g.end());
sort(s.begin(), s.end());
int result = 0;
int index = s.size() - 1;
// 利用大饼干先去满足大胃口的孩子
for (int i = g.size() - 1; i >= 0; i--) {
if (index >= 0 && s[index] >= g[i]) {
index--;
result++;
}
}
return result;
}
};
376. 摆动序列
本题需要考虑三种情况
- 上下坡中有平坡 算1个
- 数组首尾两端
- 单调坡中有平坡 不算
默认第一个值前面有一个相同的值,产生平坡, prediff = 0, 将数组首考虑进来,result 默认为1, 将 数组尾考虑进来
最后当坡度变化时再将 prediff 变为 curdiff 将两种平坡的情况考虑进来
class Solution {
public:
int wiggleMaxLength(vector<int>& nums) {
int result = 1;
int prediff = 0;
int curdiff = 0;
for (int i = 0; i < nums.size() - 1; i++) {
curdiff = nums[i + 1] - nums[i];
if (prediff >= 0 && curdiff < 0 || prediff <= 0 && curdiff > 0) {
result++;
prediff = curdiff;
}
}
return result;
}
};
53. 最大子序和
局部最优:当前“连续和”为负数的时候立刻放弃,从下一个元素重新计算“连续和”,因为负数加上下一个元素 “连续和”只会越来越小。
全局最优:选取最大“连续和”
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int result = INT32_MIN;
int tmp = 0;
for (int i = 0; i < nums.size(); i++) {
tmp += nums[i];
result = result < tmp ? tmp : result;
if (tmp < 0) tmp = 0;
}
return result;
}
};
参考:
卡哥代码随想录