力扣刷题记录(12)LeetCode:45、1005、135、860

文章讲述了在编程问题中,如跳跃游戏II、K次取反后的数组和、分发糖果和柠檬水找零等,如何运用贪心算法和考虑局部最优解来解决。重点介绍了在跳跃游戏中如何确定每一步跳跃的最大覆盖范围,以及在其他问题中的分类讨论和细节实现策略。
摘要由CSDN通过智能技术生成

45.跳跃游戏II

这题的解题思路关键在于如何在当前覆盖范围内寻找下一次跳跃能够覆盖的最大范围。比如示例一:第一次能够跳两个格子,当前的覆盖范围就是[2,3,1],那么2明显不能够跳到最后,所以我们需要再进行一次跳跃,也就是第二次跳跃。第二次跳跃需要我们在第一次跳跃所能覆盖的范围内寻找,也就是在[3,1]中寻找。很明显在3的位置可以跳的最远,于是我们两次跳跃后能够覆盖的范围就到了4这个位置。4已经到达最后了,结束。跳跃了两次。

class Solution {
public:
    int jump(vector<int>& nums) {
        if(nums.size()==1)  return 0;
        int nowLength=nums[0],ans=1,nextLength=0;
        for(int i=1;i<nums.size();i++)
        {
            if(nowLength>=nums.size()-1)  break;
            nextLength=max(nextLength,i+nums[i]);
            if(i==nowLength)
            {
                nowLength=nextLength;
                ans++;
            }
        }
        return ans;
    }
};

 1005.K次取反后最大化的数组和

常规思维对数组进行排序,将负数全部取反。如果转化次数还剩余,就再排序将最小值转化,直到将剩余次数耗尽。

class Solution {
public:
    int largestSumAfterKNegations(vector<int>& nums, int k) {
        sort(nums.begin(),nums.end());
        int ans=0,time=k;
        //先将负数转化为正数
        for(int i=0;i<nums.size();i++)
        {
            if(nums[i]>=0 || time==0) break;
            if(nums[i]<0)
            {
                nums[i]=nums[i]*(-1);
                time--;
            }
            
        }
        //判断是否还剩余转换次数
        //如果转换次数为0或者为偶数,直接累加即可
        if(time==0 || time%2==0)
        {
            for(int i=0;i<nums.size();i++)
            {
                ans+=nums[i];
            }
        }
        //如果剩余次数为奇数,直接在排序后改变最小值,再累加
        else
        {
            sort(nums.begin(),nums.end());
            nums[0]=nums[0]*(-1);
            for(int i=0;i<nums.size();i++)
            {
                cout<<nums[i]<<" ";
                ans+=nums[i];
            }
        }
        return ans;
    }
};

135.分发糖果

 

可以正向遍历一遍,保证如果后一个孩子的评分大于前一个孩子那后一个孩子分到的糖果就比前一个孩子分到的糖果多一个。然后再反向遍历一遍,保证如果前一个孩子的评分大于后一个孩子的评分那前一个孩子分到的糖果就比后一个孩子分到的糖果多一个。

class Solution {
public:
    int candy(vector<int>& ratings) {
        int ans=0;
        vector<int> nums(ratings.size(),1);
        //正向遍历
        for(int i=1;i<ratings.size();i++)
        {
            if(ratings[i]>ratings[i-1]) nums[i]=nums[i-1]+1;
        }
        //反向遍历
        ans+=nums[nums.size()-1];
        for(int i=ratings.size()-2;i>=0;i--)
        {
            if(ratings[i]>ratings[i+1]) nums[i]=max(nums[i],nums[i+1]+1);
            ans+=nums[i];
        }
        return ans;
    }
};

860.柠檬水找零

 

 

这题比较简单,直接分情况讨论即可。

1.收到5美元

2.收到10美元

3.收到20美元

class Solution {
public:
    bool lemonadeChange(vector<int>& bills) {
        vector<int> nums(3,0);
        for(int i=0;i<bills.size();i++)
        {
            switch(bills[i])
            {
                case 5:
                    nums[0]++;
                    break;
                case 10:
                    if(nums[0]<1)  return false;
                    nums[0]--;
                    nums[1]++;
                    break;
                case 20:
                    if(nums[1]<1)
                    {
                        if(nums[0]<3)   return false;
                        else    nums[0]-=3;
                    }
                    else
                    {
                        if(nums[0]<1) return false;
                        else    nums[0]--;
                        nums[1]--;
                    }
            }
        }
        return true;
    }
};

总结 

 1005、860这两天都是常规的思路,正常推理就可以找到解决方法,关键点在于细节的实现。要分类讨论,针对不同的结果提供不同的解决方式。45题是比较典型的贪心算法思维,重点在于如何去定位局部、如何去找局部最优解。跳跃游戏II比上一篇文章中的跳跃游戏要难一些。

跳跃游戏

局部:当前所在的格子能够到达的最远距离

局部最优:接收已经遍历过的格子所能达到最远距离,也就是提取每个格子能够到达的最远距离集合的最大值。

跳跃游戏II

局部:当前格子所能到达的范围内,下一步能够到达的距离

局部最优:提取下一步能够到达的最远距离,当需要跳下一步时,那就直接跳到能够跳到的最远距离

 

  • 12
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值