代码随想录刷题记录day28 贪心 分发饼干+摆动序列+最大子数组和
参考:代码随想录
贪心理论基础
局部最优推出全局最优
一般步骤:
- 将问题分解为若干个子问题
- 找出适合的贪心策略
- 求解每一个子问题的最优解
- 将局部最优解堆叠成全局最优解
没有固定的套路,一般都是通过举反例来推导。
455. 分发饼干
思想
贪心:
将最小的饼干先分发给胃口刚好小于等于此饼干大小的孩子。
需要先排序,然后遍历饼干大小,进行分发记录。
代码
class Solution {
public int findContentChildren(int[] g, int[] s) {
//g 表示孩子的胃口 s表示饼干的大小
//饼干分给 胃口大小<=饼干大小
if(s.length==0) return 0;
int count=0;
Arrays.sort(g);
Arrays.sort(s);
int g_index=0;
for(int i=0;i<s.length;i++){
//遍历所有的饼干数量
if(g_index<g.length && s[i]>=g[g_index]){
count++;
g_index++;
}
}
return count;
}
}
376. 摆动序列
思想
贪心:
寻找极值,极大值和极小值,中间递增或者递减的过滤即可。
怎么样判断是找到了极值点呢?通过差值preDiff前两个数的差值, curDiff当前两个数的差值
- 如果preDiff<=0 curDiff>0 比如: 2 1 3 preDiff =-1,curDiff=2
- 如果preDiff>=0 curDiff<0 比如: 1 2 1 preDiff =1,curDiff=-1
class Solution {
public int wiggleMaxLength(int[] nums) {
//统计出现极值的情况
if(nums.length==1) return 1;
int preDiff=0;//之前的差值
int curDiff=0;//当前的差值
int res=1;//默认从1开始 表示最右边的峰
for(int i=1;i<nums.length;i++){
curDiff=nums[i]-nums[i-1];
if(preDiff<=0 && curDiff>0 || preDiff>=0 && curDiff<0){
res++;
preDiff=curDiff;
}
}
return res;
}
}
53. 最大子数组和
思想
用一个count来记录连续数组的和,一旦count<0 就令count从0开始计数, -2 1 是要从1开始计数的。
同时用res来记录最大的连续数组的和。
时间复杂度是 O(n) 空间复杂度是O(1)
代码
class Solution {
public int maxSubArray(int[] nums) {
//连续数组的最大和
//贪心算法
int count=0;
int res=Integer.MIN_VALUE;
for(int i=0;i<nums.length;i++){
count+=nums[i];
if(count>res){
res=count;
}
if(count<=0) count=0;//重新开始计数
}
return res;
}
}
总结
贪心的逻辑是想不到呀。不想递归 回溯 有一个具体的模板,主要思路就是局部最优 得到全局最优。
分发饼干想到了,但是代码也没写不好。
摆动序列的单调区间
最大子数组和的count累加
继续坚持呀。