代码随想录算法训练营| 贪心算法 | 122.买卖股票的最佳时机II 55. 跳跃游戏 45.跳跃游戏II

122.买卖股票的最佳时机II

题目链接

(1)文字讲解:https://programmercarl.com/0122.%E4%B9%B0%E5%8D%96%E8%82%A1%E7%A5%A8%E7%9A%84%E6%9C%80%E4%BD%B3%E6%97%B6%E6%9C%BAII.html
(2)视频讲解:https://www.bilibili.com/video/BV1ev4y1C7na/?spm_id_from=333.788&vd_source=bca249a7a739de13f222d238e1152887
(3)题目链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/submissions/

看到代码随想录之前的想法

一开始理解错意思了,以为第一天必须要买入,所以做成了一个类似于最大子序列和的想法,美美不通过。

看到代码随想录之后的想法

随便哪一天都可以买入和卖出,所以就找差值是正数的,前一天买入然后再卖出。

本题难点

不太好想到。

代码

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int sum = 0;
        for(int i = 0; i< prices.size()-1; i++){
            sum += max(0,prices[i+1]-prices[i]);
        }
        return sum;
    }
};

122.跳跃游戏

题目链接

(1)文字讲解:https://programmercarl.com/0055.%E8%B7%B3%E8%B7%83%E6%B8%B8%E6%88%8F.html#%E6%80%9D%E8%B7%AF
(2)视频讲解:https://www.bilibili.com/video/BV1VG4y1X7kB/?spm_id_from=333.788&vd_source=bca249a7a739de13f222d238e1152887
(3)题目链接:https://leetcode.cn/problems/jump-game/

看到代码随想录之前的想法

不知道怎么写。

看到代码随想录之后的想法

考虑覆盖范围!不要具体去想到底怎么跳,而是看一下,在现有的覆盖范围里面,能不能延伸到最后一个数字。
还有一个比较巧妙的写代码的方法,一开始我本想用一个数组记录一下每个点是否能被覆盖到,然后遍历每一个数,给数组赋值变化最后check数组,但是这样消耗内存太大了,完全不需要这样。
设定一个cover值,这个就是能到的范围,在这个范围里面for循环,从每一个元素开始,能到达的最大的位置就是i+nums[i],所以只用看在目前的cover范围中,能不能通过已经有的元素跳到更远的地方,如果cover的范围一再扩大,最后包括了最后一个数,说明一定可以跳到。但是如果都已经遍历完了每一个元素能够跳到的最远的地方,最大覆盖范围还是到不了最后一个元素的话,那你怎么跳都不行了。

本题难点

(1)容易被想具体每一步怎么跳迷惑住。
(2)写代码怎么最简单。

代码

class Solution {
public:
    bool canJump(vector<int>& nums) {
        int cover = 0;
        for(int i = 0; i <= cover; i++){
            cover = max(cover, i+nums[i]);
            if(cover >= nums.size()-1) return true;
        }
        return false;
    }
};

122.跳跃游戏II

题目链接

(1)文字讲解:https://programmercarl.com/0045.%E8%B7%B3%E8%B7%83%E6%B8%B8%E6%88%8FII.html#%E6%80%9D%E8%B7%AF
(2)视频讲解:https://www.bilibili.com/video/BV1Y24y1r7XZ/?spm_id_from=333.788&vd_source=bca249a7a739de13f222d238e1152887
(3)题目链接:
https://leetcode.cn/problems/jump-game-ii/

看到代码随想录之前的想法

相比于上面一题,只要每次扩大范围的都选择最大的那个元素,并且每次扩大范围之前都要检查是否已经到到了最后一个元素,每扩大一次范围,就加一步,得出来的结果就是最小的。

看到代码随想录之后的想法

同上。

本题难点

模拟的时候需要想清楚细节。
我一直以为在这里cover一开始就要赋值成num[i],因为第一步无论你走不走都会有这样的覆盖范围,但是这样做是错的。因为这里力求最少的步数,所以相比于上一题只要一找到稍微大一点的cover就可以更新,这里必须要确保在上一步cover范围中找到最大的nums[i]+i,也就是他会走完目前的cover选出一个nextcover的最大值,到icover的时候,就会开始判断要不要扩大范围。如果一开始cover就是nums[i],那么对于[2,1]这样的,就会输出0,因为在这样的逻辑中我不走路不扩大范围也可以覆盖到最后一个数,但是只要你需要用到最大的cover值==才能覆盖,就说明你不是不走路就能通关的,而是你起码得走一步。相当于,只要你不走路,你的cover就是0,而不是nums[i], 因为当你需要用道nums[0]的时候,你就得走一步了。(对不起有些乱,没有这样的困惑的可以直接忽略这一段,如果你有的话并且没看懂我在说什么,欢迎留言和我讨论)

代码

class Solution {
public:
    int jump(vector<int>& nums) {
        //if(nums.size() == 1) return 0;
        int cover = 0, maxcor = 0,result = 0;
        for(int i = 0 ;i < nums.size(); i++){
            maxcor = max(maxcor, i+nums[i]);
            if(i == cover){
                if(cover < nums.size()-1)
                {
                    result++;
                    cover = maxcor;
                    if(maxcor >= nums.size()-1) 
                    {
                        break;
                    }
                }else{
                    break;
                }
            }
        }
        return result;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值