455. 分发饼干
题目描述
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。
对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。
示例1:
输入:g=[1,2,3],s=[1,1]g = [1,2,3], s = [1,1]g=[1,2,3],s=[1,1]
输出:111
示例2:
输入:g=[1,2],s=[1,2,3]g = [1,2], s = [1,2,3]g=[1,2],s=[1,2,3]
输出:222
思路
说实话,看到这道题,没想到啥贪心啥的,主要的思路就是非常朴素:
两个数组都按从小到大的顺序排列,然后先把小饼干给胃口小的孩子,设置计数器记录。
解法
class Solution {
public int findContentChildren(int[] g, int[] s) {
Arrays.sort(g);
Arrays.sort(s);
int count = 0;
int start = 0;
for(int i = 0;i<s.length && start < g.length;i++){
if(s[i] >= g[start]){
start++;
count++;
}
}
return count;
}
}
总结
先用小饼干喂给小胃口的孩子本身就是一种局部最优,因为对这个饼干来说,没有浪费。而每一个饼干都不浪费就是全局最优。
376. 摆动序列
题目描述
如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为 摆动序列 。第一个差(如果存在的话)可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。
例如, [1, 7, 4, 9, 2, 5] 是一个 摆动序列 ,因为差值 (6, -3, 5, -7, 3) 是正负交替出现的。
相反,[1, 4, 7, 2, 5] 和 [1, 7, 4, 5, 5] 不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。
子序列 可以通过从原始序列中删除一些(也可以不删除)元素来获得,剩下的元素保持其原始顺序。
给你一个整数数组 nums ,返回 nums 中作为 摆动序列 的 最长子序列的长度 。
示例1:
输入:nums=[1,7,4,9,2,5]nums = [1,7,4,9,2,5]nums=[1,7,4,9,2,5]
输出:666
示例2:
输入:nums=[1,17,5,10,13,15,10,5,16,8]nums = [1,17,5,10,13,15,10,5,16,8]nums=[1,17,5,10,13,15,10,5,16,8]
输出:777
示例3:
输入:nums=[1,2,3,4,5,6,7,8,9]nums = [1,2,3,4,5,6,7,8,9]nums=[1,2,3,4,5,6,7,8,9]
输出:222
思路
不得不说,本题虽然放在了贪心里面,但是看到题目之后第一时间触发的是尘封已久的不太友好的动态规划的DNA。但另一方面,动态规划也不会。。。。。。真应了那句书到用时方恨少。。。。。
直接上答案的思路了,这题真的想不到。
本题中使用贪心的局部最优在于删除单调坡度上的节点,那么这个坡度就可以拥有两个局部峰值。
整体最优在于:整个序列有最多的局部峰值,从而达到最长摆动序列。
翻译一下就是:让峰值尽可能地保持住,然后删掉一些单一坡度上的节点。
这里需要考虑三种情况:
1、上下坡中有平坡:删除平坡时的左侧相同元素,只保留最后一个相同的元素
2、数组首尾两端:默认有一个峰值
3、单调坡中有平坡:坡度变化时才更新preDiff
解法
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];
if((curDiff > 0 && preDiff <= 0)||(curDiff < 0 && preDiff >= 0)){
count++;
preDiff = curDiff;
}
}
return count;
}
}
总结
思考量很足的,但是我完全没有思考到。总结:贪心还没学会
53. 最大子序和
题目描述
给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组 是数组中的一个连续部分。
示例1:
输入:nums=[−2,1,−3,4,−1,2,1,−5,4]nums = [-2,1,-3,4,-1,2,1,-5,4]nums=[−2,1,−3,4,−1,2,1,−5,4]
输出:666
示例2:
输入:nums=[1]nums = [1]nums=[1]
输出:111
示例3:
输入:nums=[5,4,−1,7,8]nums = [5,4,-1,7,8]nums=[5,4,−1,7,8]
输出:232323
思路
如果我没记错的话,最大子序和应该是动态规划的一个经典应用叭,虽然动态规划也不会,但看题的时候还是没有贪心的感觉。感觉还是没明白它贪在了哪里。
直接上答案思路:
局部最优:当前“连续和”为负数的时候立刻放弃,从下一个元素重新计算“连续和”,因为负数加上下一个元素 “连续和”只会越来越小。
全局最优:选取最大“连续和”
从代码角度上来讲:遍历nums,从头开始用count累积,如果count一旦加上nums[i]变为负数,那么就应该从nums[i+1]开始从0累积count了,因为已经变为负数的count,只会拖累总和。
而为了能够得到最大连续和,就需要上一些手法了
看代码的话很简单,就是用count和result的比较,如果count取到最大值了,及时记录下来了。但说实话,这个小逻辑其实很有思考量的,想不到的时候真的会困在这里的。
解法
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;
}
}
return sum;
}
}
总结
总结,想不到贪心,贪心还是没学会啊,再看看。
文章介绍了使用贪心算法解决三个编程问题:如何最大化满足孩子饼干需求的数量、找到最长的摆动序列以及计算最大子序和。每个问题都展示了贪心策略如何通过局部最优决策达到全局最优解。解题过程中,涉及排序、峰值保留和连续和优化等关键步骤。

被折叠的 条评论
为什么被折叠?



