round1/day8/贪心1

1. 关于贪心

  1. 问题分析:梳理与理解问题特性,包括状态定义、优化目标和约束条件等 待施工
  2. 确定贪心策略:把问题拆分成子问题,在每个子问题中找到局部最优解(贪心选择)。
  3. 正确性证明:证明问题具有贪心选择性质和最优子结构(局部最优能够导向全局最优)
    - 反证法:假设用除了最优解以外的方法来解决问题,然后与和最优解解决相比较,发现其效果劣于最优解,说明最优解成立

贪心的应用场景

待施工

2. 例题

lc455 分发饼干

易错点

  1. 如果从小到大遍历小孩胃口,那对i他们的饼干挑选也从小到大,反之亦然,不能一正一反,想当然觉得<小孩应该从大到小遍历,而饼干应该抠着给每个人最小的那块>,注意目标是让尽可能多的小孩吃到饼干,而不是抠
  2. 还是在用嵌套循环,没有考虑到遍历一数组的时候针对另一个数组需要一个动态的游标
    startIndex<s.lengthstartIndex<=s.length-1都可以写的时候,优先写前者,因为后者会涉及到s.length=0导致出错的问题
  3. 在if里,应该先判断if(startIndex<g.length),再判断if(startIndex<g.length),如果已经超出,则g[startIndex]就会报错,不能反过来写

思路

思路:分解为:对每个孩子分饼干找最优解
思路1:以饼干为基础,优先把最小饼干分给最小胃口小孩,往上走——遍历饼干
思路2:以胃口为基础,优先把最大饼干分给最大胃口小孩,往下走——遍历胃口

代码实现

class Solution {
    public int findContentChildren(int[] g, int[] s) {
        Arrays.sort(g);
        Arrays.sort(s);
        int num=0;
        int startIndex = 0;

        for(int i=0;i<s.length;i++){
            if(startIndex<g.length && s[i]>=g[startIndex]){ 
            //注意,这里是用饼干去找胃口,先遍历小的饼干看哪块合适
                num++;
                startIndex++;
            }
        }
        return num;
    }
}

lc376 摆动序列

易错点

审题不清。不是只找连续存在摆动序列的数组,而是可以跨过几个元素建立摆动序列。所以只要找打num[next]能够和num[cur]的差值diff与prevdiff正负相反就可以

思路

  1. 一个准摆动序列点上,diff必须!=0 且与prevdiff符号相反
  2. 但是它的prevdiff可能会=0,也正是因为=0,才需要去找新的diff,故在比较差值的时候,需要给prevdiff加上=0的条件

代码实现

class Solution {
    public int wiggleMaxLength(int[] nums) {
        if (nums.length <= 1) {
            return nums.length;
        }

        int max = 1; // 最小长度为1
        int prevDiff = nums[1] - nums[0];

        if (prevDiff != 0) {
            max = 2;
        }

        for (int i = 2; i < nums.length; i++) {
            int diff = nums[i] - nums[i - 1];
            if ((diff > 0 && prevDiff <= 0) || (diff < 0 && prevDiff >= 0)) {
                max++;
                prevDiff = diff;
            } else if (diff != 0) {
                prevDiff = diff; // 开始新的摆动序列
            }
        }

        return max;
    }
}

lc53 最大子数和

我琢磨着这也不是贪心阿
与376不同,这里需要连续数组

思路

两个问题:
1.要不要在当前连续和 cursum 中继续加入 nums[i]。
2.要不要以 nums[i] 为起点,重新开始计算连续和。

注意:是以nums[i]为基准,比较它和 nums[i] + currentSum 的值,来选择:是继续cursum+=nums[i] or 还是nums[i]自立门户

代码实现

//动态规划
class Solution {
    public int maxSubArray(int[] nums) {
        if(nums.length==1){
            return nums[0];
        }
        int cursum= nums[0];
        int maxsum = nums[0];

        for(int i=1;i<nums.length;i++){
            cursum = Math.max(cursum+nums[i],nums[i]); //比较的是nums[i]和+cursum的大小,而不是反过来!
            maxsum = Math.max(cursum,maxsum);
        }
        return maxsum;
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值