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

发布时间:2023年12月18日

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

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

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

?

文章来源:https://blog.csdn.net/weixin_61759589/article/details/134989493
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。