LeeCode刷题:45. 跳跃游戏 II(C++)

心情:这是我第一次正儿八经的遇到贪婪算法!

题目:

给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。

示例:

输入: [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。
从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。

方法一:暴力

暴力确实一般来说绝对不会是最佳解法,甚至有的时候会超时,但是我想了想还是要练练,万一哪天做题实在想不出来,用暴力又不会超时呢!
省略代码。。。。。。

方法二:动态规划

描述:用dp[i]记录从i到最后一个位置的最小跳跃次数,从后往前去寻找,假设总共nsize个元素,则dp[nsize -1]=0,dp[nsize - 2]=1(这里实际上有错误,比如当nums[nsize -2]=0),然后再依次往前遍历,当遍历到i时,dp[i] = min(1+dp[i+j]),j是小于nums[i]的任意一个值,则结果就是dp[0]。

代码如下:

    int jump(vector<int>& nums) {

        int nsize = nums.size();
        if(nums.size() == 1) return 0;
        int dp[nsize] = {0};

        dp[nsize - 1] = 0;
        dp[nsize - 2] = 1;
        for(int i = nsize - 3;i >= 0;i--){
            int sum = nsize;
            for(int z = 1; z <= nums[i];z++){
                if(i+z >= nsize) break;

                sum  = min(sum,1+dp[i+z]);
            }

            dp[i] = sum;
        }

        return dp[0];

    }

这个虽然可以求解,但是超时了,并不是因为nsize太多了,而是循环的点除了nsize还有当前的值nums[i]决定了第二层循环的次数,当很大的时候,可想而知。

方法三:贪心算法

贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。

当初在学贪心算法的时候我记得一句话,贪心算法不一定是最优解,所以我每次考虑问题的时候实际上是不会朝着贪心算法去考虑的,但这题仔细品品确实可以用贪心,思路我就借用别人的图,理解很快。
在这里插入图片描述
总的来说就是选取的下一跳的距离j,使得j+nums[i+j]最大。
代码如下:

int jump(vector<int>& nums){
        int nsize = nums.size();
        int i = 0;
        int ju = 0;
        while(i < nsize-1 ){
            int sum = 0;
            int nexti = i;
            for(int j = 1;j <= nums[i];j++){
                if(j+i >= nsize - 1){
                    nexti = j+i;
                    break;
                }
                if(j+nums[j+i] > sum){
                    sum = j+nums[j+i];
                    nexti = j+i;
                }
            }

            i = nexti;
            ju++;

        }
        return ju;
    }

虽然明白了贪心算法的思路,但是我现在仍然有个疑惑?为什么这个情况下贪心算法能求出最优解呢?我想以后慢慢做题再去理会!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值