视频讲解:
贪心算法,你想先喂哪个小孩?| LeetCode:455.分发饼干_哔哩哔哩_bilibili
455.分发饼干
思路:题目中明确饼干不可以分割,而要想贪心的策略,在于每一次都可以将最小分量的饼干分给最接近其胃口的孩子。
// 时间复杂度在于排序以及遍历两部分O(mlogm+nlogn)与O(m)或O(n)比较,显然时间复杂度为O(mlogm+nlogn)
// 空间复杂度O(1)
class Solution {
public int findContentChildren(int[] g, int[] s) {
// 题目的关键在于饼干不可以分割
// 其次贪心的策略在于每一次都可以将最小分量的饼干分给最接近其胃口的孩子
Arrays.sort(g);
Arrays.sort(s);
int j = 0;
int count = 0;
for(int i=0; i<g.length; i++){
if(j == s.length)
break;
if(g[i]<=s[j]){
count++;
j++;
}
else if(g[i]>s[j]){
//当前最小的胃口都比当前饼干来的大,说明饼干需要增大了
i--;
j++;
}
}
return count;
}
}
376. 摆动序列
思路:贪心的策略就是将每一条子序列都变成忽增忽降的曲线,剔除上面存在的多个同一方向的节点。
// 时间复杂度O(n)
// 空间复杂度O(1)
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;
// 解法二,通过提出同一递增或递减方向上的其他节点完成最长摆动序列的计数
// 实际上就是统计出现拐点的个数,但是需要主要的是要讲初始的0位置直接算为一个拐点,其次针对长度为2时的数组,需要加入尾元素与首元素相等的判断,此操作蕴含在direction==-1的判断中
int res = 1;
int dierction = -1;
for(int i=1; i<nums.length; i++){
int minus = nums[i]-nums[i-1];
// 开始初步遍历以及长度为2的数组的特殊操作
if(dierction == -1){
if(minus<0) {
dierction = 0;
res++;
}
else if(minus>0) {
dierction = 1;
res++;
}
}
if(minus<0 && dierction == 1){
res++;
dierction = 0;
}
if(minus>0 && dierction == 0){
res++;
dierction = 1;
}
}
return res;
}
}
53.最大子序列的和
思路:贪心的策略在于需要每一步都保证当前的序列和是增加的,因此需要比较的目标包括sum与sum+nums[i]比较,以及sum+nums[i]与nums[i]比较,后者是防止sum是负数,而nums[i]是一个不足以使其取正的正数。其次特殊的情况在于sum与nums[i]都为负数,次数需要判断nums[i]与sum的大小,来保证取得nums[i]后序列和是增加的。
// 时间复杂度O(n)
// 空间复杂度O(1)
class Solution {
public int maxSubArray(int[] nums) {
// 贪心的思想就是每一步都需要使我的数组和变大一点
// 仅仅比较sum+nums[i]和nums[i]的原因是不管nums[i]是正是负,不断加入元素总是存在序列和增加的可能,也许当前是负数但后续全是正数.并且题目中明确序列和是需要连续的,所以核心需要判断的就是当前元素加入上总和是不是比自身更低,那么证明之前的元素的求和失去了意义,只需选择当前元素更大的数值开始往后累加从而求取更大的序列和
if(nums.length == 1)
return nums[0];
int max = nums[0];
int sum = nums[0];
int i=1;
while(i<nums.length){
// 特殊情况出现一段连续的负数,此时直接跳过
if(sum<0 && nums[i]<0){
if(sum < nums[i])
sum = nums[i];
}
else
sum = Math.max(sum+nums[i], nums[i]);
i++;
max = sum>max? sum:max;
}
return max;
}
}