贪心算法
什么是贪心算法?
个人理解就是字面意思,所谓贪心就是我都要,贪心算法的思路就是,按照你认为的归路求解最优局部解,进而根据最优局部解找到全局的最优解。
那么可能有人会疑惑,找到的局部最优解就一定就是全局的最优解吗,可以说,不一定,我的理解是在90%的情况之下,你的常识应该是对的。
那么贪心算法有类似于二叉树以及回溯算法所谓的模板吗?答案是没有,贪心算法可以非常简单,但也可以非常难,基本上就是一个极端,所以说,对待贪心算法要多多掌握思路,多刷,见得多了们也就会做了
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。
对每个孩子 i
,都有一个胃口值 g[i]
,这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j
,都有一个尺寸 s[j]
。如果 s[j] >= g[i]
,我们可以将这个饼干 j
分配给孩子 i
,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。
解题思路:
要将n个不同的饼干分发给s个孩子,并且饼干的大小不一样,孩子的胃口也不一样,根据贪心的策略,我们首先将孩子的胃口和饼干的大小进行排序,将小的饼干分发给胃口西小孩子,由此不断重复,就会尽可能保证多的孩子分配到适合胃口的饼干。
代码解决-使用贪心的思路,运用双指针实现,当然两个for循环也是阔以的
class Solution {
public int findContentChildren(int[] g, int[] s) {
if(s.length<=0) return 0;
int result=0;
///首先对胃口和饼干大小进行排序
Arrays.sort(g);
Arrays.sort(s);
int sl=0;
int gl=0;
while(sl<s.length&&gl<g.length){
if(s[sl]>=g[gl]){
result++;
sl++;
gl++;
}else if(s[sl]<g[gl]) sl++;
}
return result;
}
}
如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为 摆动序列 。第一个差(如果存在的话)可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。
-
例如,
[1, 7, 4, 9, 2, 5]
是一个 摆动序列 ,因为差值(6, -3, 5, -7, 3)
是正负交替出现的。 - 相反,
[1, 4, 7, 2, 5]
和[1, 7, 4, 5, 5]
不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。
子序列 可以通过从原始序列中删除一些(也可以不删除)元素来获得,剩下的元素保持其原始顺序。
给你一个整数数组 nums
,返回 nums
中作为 摆动序列 的 最长子序列的长度 。
解题思路:
本题所说的摆动序列的最长子序列的长度就是在整个数组之中出现峰值算作一个长度,如果出现连续的坡度,只记录为一个,如下图,打❌的地方就不需要记录。
此题贪心的思路我认为就是对数组遍历,遇到峰值就进行记录+1,具体实现为
使用prefiff=nums[i]-nums[i-1];
curdiff=nums[i+1]-nums[i]
如果说两个结果相反,说明存在峰值我们进行结果累加
但是需要注意的是,有几种临界值需要处理
1,存在平坡
2,只有两个元素
处理的细节就是prediff是否为0
class Solution {
public int wiggleMaxLength(int[] nums) {
if(nums.length==1) return 1;
int res=1;
int prediff=0;
int curdiff=0;
for(int i=0;i<nums.length-1;i++){
curdiff=nums[i+1]-nums[i];
if(curdiff>0&&prediff<=0
||curdiff<0&&prediff>=0){
res++;
prediff=curdiff;
}
}
return res;
}
}
给你一个整数数组 nums
,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组 是数组中的一个连续部分。
解题思路:
感觉这道题的解题思路十分直白,我们可以直接使用两个for循环,进行暴力穷举,将子数组的值不断的和maxValue进行对比,更新,循环结束之后保留的macValue就是最大的子数组之和,
但是这种情况会超时,因为他的时间内复杂度是恐怖的O(n*2)。
使用贪心算法,这里我们默认的局部最优解就是前n个大于0的子数组,如果第n+1个小于0了,那莫我们直接跳过当前子序列,重新求解局部最优解,当循环遍历完成之后这时的局部最优解中的最优解就是我们全局的最优解。不要问我为什莫??这是感觉。
//首先使用暴力解法尝试
/ class Solution {
// public int maxSubArray(int[] nums) {
// int maxsum=Integer.MIN_VALUE;
//
// //暴力解法的思路没有问题,但是会超时,因此不推荐
// for(int i=0;i<nums.length;i++){
// int count=0;
// for(int j=i;j<nums.length;j++){
// if(nums[j]<0) j++;
// count+=nums[j];
// maxsum=maxsum>count?maxsum:count;
// }
// }
// return maxsum;
// }
// }
//使用贪心算法
class Solution {
public int maxSubArray(int[] nums) {
//如何求解局部最优解
//从第一个开始累加结果,当遇到累加的数字导致前面的和小于0,说明
//这个值就不能取,摒弃之后开始取下一个局部最优解
int count=0;
int result=Integer.MIN_VALUE;
for(int i=0;i<nums.length;i++){
count+=nums[i];
//判断当前是否是局部最优
if(count>result) result=count;
//如果当前值导致和小于0,直接将结果集清空,找寻下一个最优解。
if(count<0) count=0;
}
return result;
}
}
Create The Code! Change The World!
By三条直线围墙