分发饼干
这里的局部最优就是大饼干喂给胃口大的,充分利用饼干尺寸喂饱一个,全局最优就是喂饱尽可能多的小孩
这里只用一个for循环, 因为在外面定义了分发的饼干和饼干数组的下标(注意这个index就是用来遍历数组的), 然后for循环里面是遍历小孩
class Solution {
public int findContentChildren(int[] g, int[] s) {
//用大饼干先喂饱胃口大的
//先要进行排序
Arrays.sort(g);
Arrays.sort(s);
//定义饼干, 和下标
int cookieIndex= s.length - 1;
int numCookie = 0;
//开始遍历小孩, 因为要保证饼干全被分配完
for(int i = g.length - 1; i >= 0; i--){
//如果饼干数量大于等于0, 同时满足胃口, 那么就喂
//这里的判断条件注意一下,
if(cookieIndex >= 0 && g[i] <= s[cookieIndex]){
numCookie++;
cookieIndex--;
}
}
return numCookie;
}
}
摆动序列
局部最优:删除单调坡度上的节点(不包括单调坡度两端的节点),那么这个坡度就可以有两个局部峰值。
整体最优:整个序列有最多的局部峰值,从而达到最长摆动序列。
这里的删除并不是真正的删除, 只需要统计峰值的数量就行了, 定义preDiff和curDiff, 其实与之前的链表又异曲同工之妙
很多细节!
- 一开始默认有峰值res = 1
- for循环遍历时, i定义为1, 因为计算式i - (i - 1)
- 后面的if判断需要写等于0的情况, 就是表示初始的preDiff
class Solution {
public int wiggleMaxLength(int[] nums) {
//如果小于等于1,肯定直接return就行了
if(nums.length <= 1){
return nums.length;
}
//开始定义差值和结果
int preDiff = 0;
int curDiff = 0;
//默认就有1个峰值
int res = 1;
//有几个边界问题,i从1开始, i<nums.length, 因为下标从0开始
for(int i = 1; i < nums.length; i++){
curDiff = nums[i] - nums[i -1];
//等于0的情况表示初始时的preDiff
if((preDiff >= 0 && curDiff < 0) || (preDiff <= 0 && curDiff > 0)){
res++;
preDiff = curDiff;
}
}
return res;
}
}
最大子序和
非常妙的贪心思想, 局部最优:当前“连续和”为负数的时候立刻放弃,从下一个元素重新计算“连续和”,因为负数加上下一个元素 “连续和”只会越来越小, 然后用max来更新result
class Solution {
public int maxSubArray(int[] nums) {
if(nums.length == 1){
return nums[0];
}
//关键点在于定义count和result
//根据局部最优得到
int result = Integer.MIN_VALUE;
int count = 0;
for(int i = 0; i < nums.length; i++){
count += nums[i];
//如果count记录的值比result大,就记录
result = Math.max(result, count);
//如果count为负值了, 就直接舍弃重置
if(count <= 0){
count = 0;
}
}
return result;
}
}