贪心算法没有固定的套路,难点就是图和通过局部最优,推出整体最优。
最好的策略就是举反例,想不到范例,那就可以试一试贪心。
想清楚局部最优和全局最优,感觉局部最优可以推出全局最优,并想不出返例,就可以试试贪心。
分发饼干
https://leetcode-cn.com/problems/assign-cookies/submissions/
这里的局部最优解就是大饼干喂给胃口大的,充分利用饼干尺寸,全局最优就是喂饱尽可能多的小孩。
class Solution {
public:
int findContentChildren(vector<int>& g, vector<int>& s) {
sort(g.begin(), g.end());
sort(s.begin(), s.end());
int res = 0;
for (int i = 0; i < s.size(); i ++) {
if (res < g.size() && g[res] <= s[i])
res ++ ;
}
return res;
}
};
摆动序列
https://leetcode-cn.com/problems/wiggle-subsequence/
局部最优:将一个单调序列中除了两个峰值的其它元素删除掉
全局最优:将序列中的所有单调部分除了局部峰值都删除掉
class Solution {
public:
int wiggleMaxLength(vector<int>& nums) {
if (nums.size() <= 1) return nums.size();
int curDiff = 0; // 当前一对差值
int preDiff = 0; // 前一对差值
int result = 1; // 记录峰值个数,序列默认序列最右边有一个峰值
for (int i = 0; i < nums.size() - 1; i++) {
curDiff = nums[i + 1] - nums[i];
// 出现峰值
if ((curDiff > 0 && preDiff <= 0) || (preDiff >= 0 && curDiff < 0)) {
result++;
preDiff = curDiff;
}
}
return result;
}
};
最大子序和
https://leetcode-cn.com/problems/maximum-subarray/
局部最优:当前连续和为负数时立刻放弃,从下一个元素重新计算连续和
全局最优:选取最大连续和
// 贪心
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int res = -100000;
int count = 0;
for (int i = 0; i < nums.size(); i++) {
count += nums[i];
res = max(count, res);
if (count < 0) count = 0; // 如果前面的子序列和小于0,那么就不要选了
}
return res;
}
};
// 动规
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int dp[100005];
dp[0] = nums[0];
int res = dp[0];
for (int i = 1; i < nums.size(); i++) {
dp[i] = max(dp[i - 1] + nums[i], nums[i]); // 状态转移
res = max(dp[i], res);
}
return res;
}
};