贪心的本质是选择每一阶段的局部最优,从而达到全局最优
贪心算法一般分为如下四步:
- 将问题分解为若干个子问题
- 找出适合的贪心策略
- 求解每一个子问题的最优解
- 将局部最优解堆叠成全局最优解
1.分发饼干
先将饼干数组和小孩数组排序。
然后从后向前遍历小孩数组,用大饼干优先满足胃口大的,并统计满足小孩数量
java
class Solution {
public int findContentChildren(int[] g, int[] s) {
// 1. sort
Arrays.sort(g);
Arrays.sort(s);
int count = 0;
int sindex = s.length - 1;
// 倒序遍历小孩数组,如果排序后饼干最大满足该小孩胃口,count++,sindex--;
for (int i = g.length - 1; i >= 0; i--) {
if (sindex >= 0 && s[sindex] >= g[i]) {
count++;
sindex--;
}
}
return count;
}
}
2.摆动序列
考虑三种情况:
- 情况一:上下坡中有平坡
- 情况二:数组首尾两端
- 情况三:单调坡中有平坡
java
class Solution {
public int wiggleMaxLength(int[] nums) {
if (nums.length <= 1) {
return nums.length;
}
int curDiff = 0;// 当前差值
int preDiff = 0;// 上一个差值
int count = 1;
for (int i = 1; i < nums.length; i++) {
// 当前差值
curDiff = nums[i] - nums[i - 1];
//如果当前差值和上一个差值为一正一负
//等于0的情况表示初始时的preDiff
if ((curDiff > 0 && preDiff <= 0) || (curDiff < 0 && preDiff >= 0)) {
count++;
preDiff = curDiff;
}
}
return count;
}
}
3.最大子序列和
(1)遍历记录最大子序列和
(2)发现前一段子序列和为负,要更新子序列和起始位置
java
class Solution {
public int maxSubArray(int[] nums) {
if (nums.length == 1) return nums[0];
int sum = Integer.MIN_VALUE;
int count = 0;
for (int i = 0; i < nums.length; i++) {// 贪心,记录区间累计最大值
count += nums[i];
sum = Math.max(sum, count);
if (count <= 0) count = 0; // 重置最大子序列和起始位置,如果count < 0,要去掉之前的序列。
}
return sum;
}
}