贪心法
贪心的本质是选择每一阶段的局部最优,从而达到全局最优。
贪心法没有固定的套路,也没有严格的证明,如果举不出范例,即可试试贪心。
贪心算法一般分为如下四步:
- 将问题分解为若干个子问题
- 找出适合的贪心策略
- 求解每一个子问题的最优解
- 将局部最优解堆叠成全局最优解
455.分发饼干
完成
思路:
对饼干和胃口排序,对于当前最小的胃口,只要能找到一块最小的饼干满足他,就算进结果。
代码
class Solution {
public int findContentChildren(int[] g, int[] s) {
int res = 0;
// 对饼干和胃口排序
Arrays.sort(s);
Arrays.sort(g);
// 双指针
int si = 0;
int gi = 0;
while(si<s.length && gi<g.length){
if(s[si]<g[gi]){ // 不满足胃口
si++;
}else{ // 满足胃口
res++;
si++;
gi++;
}
}
return res;
}
}
376. 摆动序列
完成
思路:
有点难想,需要把三种情况都考虑到位。
代码
class Solution {
public int wiggleMaxLength(int[] nums) {
if(nums.length<=1) return nums.length;
int curDif = 0;
// 这里初始为0,即默认给最左端添加了一个平峰
int preDif = 0;
// res初始值为1,即默认把最右端算进结果
int res = 1;
for (int i = 0; i < nums.length-1; i++) {
curDif = nums[i+1] - nums[i];
// 峰值,preDif==0把平峰的情况也考虑进去
if((preDif <= 0 && curDif > 0) || (preDif >= 0 && curDif < 0)){
res++;
preDif = curDif; //只在摆动变化的时候更新prediff
}
}
return res;
}
}
53. 最大子序和
完成
思路:
本题最理想的情况是把所有的负数全部去掉,但题目要求连续子数组,那就不得不保留被正数包夹的负数,即两端的负数可以直接去掉。
同时,如果该负数比两端包夹的正数之和还大,那也舍弃。
一开始的想法是算出起始位置和终止位置,再把中间的元素相加得到结果。其实题目只要求最大和,不要求明确的起始和终止位置,在过程中把最大和记下来即可。
代码
class Solution {
public int maxSubArray(int[] nums) {
// 这里不能写0,防止数组全为负数
int max = Integer.MIN_VALUE;
int sum = 0;
for (int i = 0; i < nums.length; i++) {
sum+=nums[i];
if(sum>max) max=sum;
// <0则之前的都丢弃
if(sum<0) sum=0;
}
return max;
}
}