D27|贪心算法,对不起想做出贪心问题我真是贪心

文章分析了LeetCode中的三个编程问题,包括分发饼干的贪心算法、摆动序列的峰值计数和最大子数组和的动态规划方法,展示了如何利用排序和贪心思想解决这些问题。
摘要由CSDN通过智能技术生成

好久没有这种一道题都做不出来的崩溃了。。。

455.分发饼干

初始思路:

        首先对数组进行排序,然后使用最小可以满足孩子需求的饼干,去喂给孩子,这样就可以让更多的孩子满足有饼干吃。

class Solution {
    public int findContentChildren(int[] g, int[] s) {
      int result = 0;
        int i = 0;
        int j = 0;
        Arrays.sort(g);
        Arrays.sort(s);
        while(i<g.length&&j<s.length){
            if (s[j]<g[i]){j++;}
            else if(s[j]>=g[i]){j++;i++;}
            
        }
        result = i;


        return result;
    }
    
}

题解复盘: 

        这里的题解参考了力扣中的题解,因为思路差不多易于理解。

        贪心策略我们每次从剩下的孩子中,找出胃口最小的孩子,给他能满足他胃口的最小尺寸饼干即可,这样我们得到的分配方案,是满足孩子的个数最大的

class Solution {
    public int findContentChildren(int[] g, int[] s) {
        // 将胃口和饼干排序
        Arrays.sort(g);
        Arrays.sort(s);
        // 孩子的数量
        int n = g.length;
        // 饼干的数量
        int m = s.length;
        // 记录结果
        int res = 0;
        for(int i = 0; i < m; i++){
            // 从胃口小的开始喂
            if(res < n && g[res] <= s[i]){
                res += 1;
            }
        }
        return res;
    }
}


作者:编程文青李狗蛋
链接:https://leetcode.cn/problems/assign-cookies/solutions/2103923/acm-xuan-shou-tu-jie-leetcode-fen-fa-bin-wnql/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

        大概理解一下就是,for循环遍历的是饼干,如果当前饼干不足以满足当前小孩的胃口,就i++,看看下一块饼干是否可以满足当前小孩的胃口,如果满足res+1,代表已经满足一个小孩的要求,并且res+1同时代表指针移动到下一个小孩,看看是否可以满足其需求,此处还需注意,满足小孩的个数一定需要小于小孩本身的个数。


376.摆动序列

初始思路:

        

        其实感觉对于示例1和示例3都比较好解决,因为只需要判断当前整个序列是否满足摆动序列,而无需考虑删除元素,对于序列2删除元素从而获得最小的摆动子序列实在是不是很理解如何操作。

题解复盘:

        感觉这个示例二的解释也太误导了,正确的理解思路是:

       贪心思路:

        思路上是我删除单调坡度上的节点,这个坡度上我就有两个局部峰值,当我拥有最多的局部峰值,我从而就拥有了最长的摆动序列。

        实际操作上是其实连删除的操作都不用做,因为题目要求的是最长摆动子序列的长度,所以只需要统计数组的峰值数量就可以了(相当于是删除单一坡度上的节点,然后统计长度)

        在实际操作中需要注意三种特殊情况:

        1)平坡:

                (preDiff <= 0 && curDiff > 0) || (preDiff >= 0 && curDiff < 0)

        2)首尾:默认最右面有一个峰值并且为最左添加平坡,这样首尾就可以使用相同的计算规则同其他数据点。

相同数字连续 的时候, prediff = 0 ,curdiff < 0 或者 >0 也记为波谷。

那么为了规则统一,针对序列[2,5],可以假设为[2,2,5],这样它就有坡度了即 preDiff = 0,如图:

376.摆动序列1

针对以上情形,result 初始为 1(默认最右面有一个峰值),此时 curDiff > 0 && preDiff <= 0,那么 result++(计算了左面的峰值),最后得到的 result 就是 2(峰值个数为 2 即摆动序列长度为 2)

        3)平坡2.0

         只需要在 这个坡度 摆动变化的时候,更新 prediff 就行,这样 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];
            //如果当前差值和上一个差值为一正一负
            //等于0的情况表示初始时的preDiff
            if ((curDiff > 0 && preDiff <= 0) || (curDiff < 0 && preDiff >= 0)) {
                count++;
                preDiff = curDiff;
            }
        }
        return count;
    }
}

53.最大子数组和 

初始思路:

        很混乱,可以通过运行示例,但是无法全部AC。

题解复盘:

        如果当前的和是正数,肯定会对后面的数值起到增益作用,所以保留。

        如果当前的和是负数,肯定会对后面的数值起到削减作用,不如直接从0开始。(加一个负数不如加一个0)

class Solution {
    public int maxSubArray(int[] nums) {
      int sum = 0;
      int result = Integer.MIN_VALUE;
      for(int i = 0;i<nums.length;i++){
        sum = sum+nums[i];
        result = sum>result?sum:result;
        if(sum<0){sum=0;}
      }
      return result;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值