贪心算法其实就是没有什么规律可言,所以大家了解贪心算法 就了解它没有规律的本质就够了。
不用花心思去研究其规律, 没有思路就立刻看题解。
基本贪心的题目 有两个极端,要不就是特简单,要不就是死活想不出来。
学完贪心之后再去看动态规划,就会了解贪心和动规的区别。
理论基础
定义:选择每一阶段的局部最优,从而达到全局最优。
什么时候用贪心?:手动模拟感觉可以通过局部最优推出整体最优就可以试一试。
步骤:
- 将问题分解为若干个子问题。
- 找到合适的贪心策略
- 求解每个子问题的最优解
- 将局部最优解堆叠成全局最优解
LC 455.分发饼干
题目链接:LC 455.分发饼干
思路:大饼干给小朋友亏了,但是若大饼干给胃口大的朋友也不会满足,所以,要将饼干从大到小排序,将小朋友的胃口也从大到小排序,当大饼干可以满足朋友的胃口就给这个朋友分,若满足不了就向后遍历小朋友,直到可以满足。最多可以满足的人数为饼干个数。
代码:
class Solution {
public:
int findContentChildren(vector<int>& g, vector<int>& s) {//g为小朋友的胃口,s为饼干大小
//对饼干和小朋友从大到小排序
sort(g.rbegin(),g.rend());
sort(s.rbegin(),s.rend());
int result = 0;//统计满足小朋友的个数
int num = 0;//统计吃到的饼干的id
for(int i=0; i<g.size(); i++){
if(num>=s.size())break;
if(g[i]<=s[num]){
result++;
num++;
}
}
return result;
}
};
LC 376. 摆动序列
题目链接:LC 376. 摆动序列
思路:删除单调坡上的节点,如果一个节点对于后面的节点与对前面的节点的差正负不同,那么这个节点就是钟摆点,统计钟摆点的个数,并且加上最右边的数。因为到了最后一个节点不能计算它与后面节点的差,就直接加上该节点了。每次计算i+1与i的差,若与之前的差不同,就加上点i。
代码:
class Solution {
public:
int wiggleMaxLength(vector<int>& nums) {
int result=1;
if(nums.size()<=1)return nums.size();
int curDiff=0;//当前差值
int perDiff=0;//前一轮差值
for(int i=0; i<nums.size()-1; i++){
curDiff = nums[i+1] - nums[i];
if((curDiff>0&&perDiff<=0) ||(perDiff>=0&&curDiff<0)){
result++;
perDiff = curDiff;//这样per只要开始不为0,之后就再也不会为0
}
}
return result;
}
};
LC 53. 最大子序和
题目链接:LC 53. 最大子序和
思路:用result保存遍历中子序列最大的和,用sum遍历子序列的和;当sum加上遍历的值大于0时就一直往后累加,当sum加上遍历的值小于0时就不累加,从后面重新开始统计;当sum大于result时,就更新result。
代码:
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int sum = 0;
int result = INT_MIN;
for(int i=0; i<nums.size(); i++){
sum = sum+nums[i];
//当sum大于reuslt就更新result
if(sum>result){
result = sum;
}
//当sum<0时,加后面的值也是拉低后面的累加和,那么就重新开始计数
if(sum<0){
sum=0;
}
}
return result;
}
};