Day27–贪心–455. 分发饼干,376. 摆动序列,53. 最大子数组和
贪心理论基础
摘自《代码随想录》:
- 说实话贪心算法并没有固定的套路。
- 贪心的思路就是:如何通过局部最优,推出整体最优。
- 那么如何能看出局部最优是否能推出整体最优呢?有没有什么固定策略或者套路呢?
- 不好意思,也没有! 靠自己手动模拟,如果模拟可行,就可以试一试贪心策略,如果不可行,可能需要动态规划。
- 有同学问了如何验证可不可以用贪心算法呢?
- 最好用的策略就是举反例,如果想不到反例,那么就试一试贪心吧。
- 这么个意思:刷题或者面试的时候,手动模拟一下感觉可以局部最优推出整体最优,而且想不到反例,那么就试一试贪心。
455. 分发饼干
思路:
遍历饼干,遇到孩子合适的的就分了。下一个孩子
class Solution {
public int findContentChildren(int[] g, int[] s) {
// 要有序
Arrays.sort(g);
Arrays.sort(s);
int count = 0;
int p = 0;
// 遍历饼干,遇到孩子胃口小的就分了。下一个孩子
for (int i = 0; i < s.length && p < g.length; i++) {
if (s[i] >= g[p]) {
count++;
p++;
}
}
return count;
}
}
376. 摆动序列
记录:自己写了快一小时没写出来。还是去参考题解,下次重写。
思路:
- 无序手动“删除”元素,因为只需要统计长度,不需要返回具体的元素。
- 如果当前差值和上一个差值为一正一负的时候,纳入有效元素,计算长度。
class Solution {
public int wiggleMaxLength(int[] nums) {
if (nums.length <= 1) {
return nums.length;
}
//当前差值
int curDiff = 0;
//上一个差值
int preDiff = 0;
// 从第二个开始遍历,所以初始化count=1
int count = 1;
for (int i = 1; i < nums.length; i++) {
//得到当前差值
curDiff = nums[i] - nums[i - 1];
//如果当前差值和上一个差值为一正一负(等于0的情况表示初始时的preDiff)
// 这个if已经实现“删除”元素的效果了,能进入preDiff就是有效的元素
if ((curDiff > 0 && preDiff <= 0) || (curDiff < 0 && preDiff >= 0)) {
count++;
preDiff = curDiff;
}
}
return count;
}
}
53. 最大子数组和
思路:
如果累计和是负数,那么加上前者肯定会变小,所以要更新为零,从本节点开始往后看
class Solution {
public int maxSubArray(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
int currentSum = 0;
// 这里maxSum不能初始化为0,要考虑负数的情况
int maxSum = Integer.MIN_VALUE;
for (int i = 0; i < nums.length; i++) {
// 如果累计和是负数,那么加上前者肯定会变小,所以要更新为零,从本节点开始往后看
if (currentSum < 0) {
currentSum = 0;
}
currentSum += nums[i];
maxSum = Math.max(maxSum, currentSum);
}
return maxSum;
}
}
推荐阅读:
《代码随想录》:其关键在于:不能让“连续和”为负数的时候加上下一个元素,而不是 不让“连续和”加上一个负数。