贪心算法
455.分发饼干
贪心法:
对饼干和小孩胃口进行排序, 按从小到大对每个小孩都找到其最近的满足其胃口的饼干
代码:
class Solution {
public int findContentChildren(int[] g, int[] s) {
Arrays.sort(g);
Arrays.sort(s);
int ans = 0;
for(int i=0,j=0; i<g.length && j<s.length;){
if(g[i] <= s[j]) {
i++;
ans++;
}
j++;
}
return ans;
}
}
376.摆动序列
贪心法:
- 画图法不难看出, 摆动序列的位置要么是波谷要么是波峰, 统计出来所有的波谷和波峰即可
- 初始化prediff代表前一个被统计的位置, currDiff代表当前位置的差值
- 若当前差值和前一个差值异号, 则代表遇到一个波峰或者波谷, ans++
- 同时, 更新preDiff为currDiff,寻找下一个异号的位置, 依次规避上升序列和下降序列
代码:
class Solution {
public int wiggleMaxLength(int[] nums) {
if(nums.length < 2) return 1;
int preDiff = 0, currDiff = 0, ans = 1;
for(int i=1; i<nums.length; i++){
currDiff = nums[i] - nums[i-1];
if((currDiff > 0 && preDiff <= 0) || (currDiff < 0 && preDiff >= 0)){
ans++;
preDiff = currDiff;
}
}
return ans;
}
}
解法二:
动态规划
维护两个遍历, 一个记住下降时的最长子序列长度, 一个记住上升时的最长子序列长度
- 当下降时, 那么此时的最长子序列长度就等于在之前上升时的最长长度+1
- 当上升时, 那么此时的最长子序列长度就等于在之前下降时的最长长度+1
代码:
class Solution {
public int wiggleMaxLength(int[] nums) {
int down = 1, up = 1;
for (int i = 1; i < nums.length; i++) {
if (nums[i] > nums[i - 1])
// 上升区间, 在前一个下降时的个数基础上+1
up = down + 1;
else if (nums[i] < nums[i - 1])
// 下降区间, 在前一个上升时的个数基础上+1
down = up + 1;
}
return nums.length == 0 ? 0 : Math.max(down, up);
}
}
53.最大子数组和
解法1: 贪心
- 对于一个前缀和, 若加上当前数字nums[i], 使得总和变大, 则代表当前序列需要前缀和
- 若加上当前数字nums[i], 使得总和变小, 则代表当前序列不需要前缀和, 直接从当前数字开始一个序列即可
- 另外, 需要用一个变量不断的记录遍历过程中的最大子数组和
代码:
class Solution {
// 最大连续子数组和
public int maxSubArray(int[] nums) {
int sum = nums[0], ans = nums[0];
for(int i=1; i<nums.length; i++){
sum = Math.max(sum + nums[i], nums[i]);
ans = Math.max(ans, sum);
}
return Math.max(ans, sum);
}
}
解法2: 动态规划
递推式和贪心一致