理论基础:
贪心的本质:选取每一阶段的局部最优从而达到全局最优。
步骤:
(1)将问题分解为若干个子问题。
(2)找出合适的贪心策略。
(3)求姐妹一个子问题的最优解。
(4)将局部最优解堆叠成全局最优解。
Leetcode - 455:分发饼干
大尺寸饼干优先满足胃口大的孩子,而局部最优解就是将大尺寸的饼干分配给胃口大的孩子。优先满足胃口大的孩子,依次向后分配。
class Solution {
public:
int findContentChildren(vector<int>& g, vector<int>& s) {
sort(g.begin(), g.end());
sort(s.begin(), s.end());
int index = s.size() - 1;
int count = 0;
for(int i = g.size() - 1; i >= 0; i--){
if(index >= 0 && s[index] >= g[i]){
count++;
index--;
}
}
return count;
}
};
class Solution {
public:
int findContentChildren(vector<int>& g, vector<int>& s) {
sort(g.begin(), g.end());
sort(s.begin(), s.end());
int s_index = s.size() - 1;
int g_index = g.size() - 1;
int count = 0;
while(s_index >= 0 && g_index >= 0){
if(g[g_index] <= s[s_index]){
count++;
s_index--;
}
g_index--;
}
return count;
}
};
Leetcode - 376:摆动序列
这道题难点在于找到异常情况并找到应对的策略:
(1)开头处的pre怎么赋值:
这里分开局上下坡的不同情况:一种是开局下坡:pre = 0 && cur < 0,一种是开局上坡:pre = 0 && cur > 0。
(2)遍历过程中出现平坡的过程:
这里我们只选取平坡当中的最后一个点,也就是遇到平坡时我们不对pre赋值,pre保持不动我们的cur一直在前进,当cur != 0的时候,我们再将cur赋值给pre,两者一起移动。
if(pre <= 0 && cur > 0 || pre >= 0 && cur < 0){
count++;
pre = cur;
}
class Solution {
public:
int wiggleMaxLength(vector<int>& nums) {
int cur = 0;
int pre = 0;
int count = 1;
if(nums.size() == 1){
return count;
}
for(int i = 0; i < nums.size(); i++){
if(i + 1 < nums.size()){
cur = nums[i + 1] - nums[i];
}
if(cur > 0 && pre <= 0 || cur < 0 && pre >= 0){
count++;
pre = cur;
}
}
return count;
}
};
Leetcode - 53:最大子数组和
这道题的思路是:选取局部最优:就是如果加上当前的元素count < 0那么count就从0开始技术,也就是从下一个元素开始再算区间和。
if(count < 0) count = 0;
我们遍历数组,当count > res的时候,就将count赋值给res记录结果。
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int res = -1e5;
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;
}
};