贪心算法介绍
贪心算法:贪心的本质是选择每一阶段的局部最优,从而达到全局最优。
说实话贪心算法并没有固定的套路。
一般解题步骤
- 贪心算法一般分为如下四步:
① 将问题分解为若干个子问题
② 找出适合的贪心策略
③ 求解每一个子问题的最优解
④ 将局部最优解堆叠成全局最优解
455.分发饼干
局部最优就是找到大饼干喂胃口大的小孩 ,也可以是找到小饼干喂胃口小的小孩
- 错误写法:
我的思路是从大到小遍历饼干,如果当前饼干能满足当前孩子,那么继续;如果不能,一定要找到第一个能被这块饼干满足的孩子。
class Solution {
public int findContentChildren(int[] g, int[] s) {
if(s.length == 0) return 0;
Arrays.sort(g);
Arrays.sort(s);
//思路是,把从小到大的饼干先分配了?还是从大到小
//局部最优就是浪费最少的饼干差 min(s[j]-g[i])
int i = g.length-1;
int sum = 0;
for(int j = s.length-1; j >= 0; j--) {
if(i>=0 && s[j] >= g[i]) {
sum++;
i--;
} else {
while(i>=0 && s[j]<g[i]) {
i--;
}
if(i<0) break;
sum++;
}
}
return sum;
}
}
为什么错呢?可以看示例解答,遍历饼干的话,[1,1]两个元素同时能满足 [1,2,3]中的第一个,所以记为了2,但实际上答案是1。只需修改一句话,就变成正确的了。
- 写法2:
不遍历饼干了,遍历孩子。
376. 摆动序列
首先,没有理解题意,题目是要求删除元素的
遇到摆动(峰值)结果就++,遇到坡度上的值/平坡上的值,就不++。
遍历到i元素的时候,prediff=nums[i]-nums[i-1],curdiff=nums[i+1]-nums[i],当prediff*curdiff<0,那么就++。
但是有几种特殊情况 ①平坡(有摆动、无摆动),②首尾元素(不遍历最后一个元素,默认它有一个摆动)对于首元素,可以添加一个prediff 也就是虚拟的nums[-1] = nums[0]
局部最优:删除单调坡度上的节点(不包括单调坡度两端的节点),那么这个坡度就可以有两个局部峰值。
整体最优:整个序列有最多的局部峰值,从而达到最长摆动序列。
class Solution {
public int wiggleMaxLength(int[] nums) {
if(nums.length < 1) return nums.length;
int curdiff=0,prediff=0,count=1;
for(int i=1; i<nums.length; i++) {
// prediff=nums[i]-nums[i-1]; 不需要
curdiff=nums[i]-nums[i-1];
if(prediff<=0&&curdiff>0 || prediff>=0&&curdiff<0) {
count++;
prediff = curdiff;
}
}
return count;
}
}
53. 最大子序和
一定要想到暴力法:两层for循环
分析:
连续和+nums[i],如果连续和为负数,nums[i]为正数,不如直接抛弃连续和。只要连续和不是负数,都对后续的和起到一个增加作用。
class Solution {
public int maxSubArray(int[] nums) {
if(nums.length == 1) return nums[0];
int count=0, res=Integer.MIN_VALUE;
for(int i=0; i<nums.length; i++) {
if(count < 0) {
count = nums[i];
} else {
count += nums[i];
}
res = count>res?count:res;
}
return res;
}
}