leetcode45. 跳跃游戏Ⅱ

给定一个非负整数数组,你最初位于数组的第一个位置。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

你的目标是使用最少的跳跃次数到达数组的最后一个位置。

示例:

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

说明:

假设你总是可以到达数组的最后一个位置。

正确思路:

https://blog.csdn.net/scarlett_guan/article/details/80159621

贪心算法:

思路:贪心法来做,时间复杂度O(n). 用变量aa来记录上一次能达到的最远位置,times记录所用的最小跳跃数,说明times步区能达到的最远位置是aa,比如在input{ 7, 0, 9, 6, 9, 6, 1, 7, 9, 0, 1, 2, 9, 0, 3},这个区间内,1步区所能达到的最远位置是7。在 i 到达aa(7)之前,所有的位置都可以通过times步数(1步)来达到,因此这个区间之内,每一个点当前可以达到的最远位置bb= max(bb, nums[i]+i),最小跳跃数为times+1(2步)。到了i=aa(即i==7)的时候,更新aa=max(bb, aa+nums[aa])=14, ++times, 也就是说标志着1步区的结束,2步区的开始,此时2步区所能达到的最远位置为aa=14。成为下一阶段3步区的前一个最优解。重复该过程。

class Solution {
public:
    int jump(vector<int>& nums) {
        if (nums.size() == 1) return 0;
        int aa = nums[0], times = 1, bb=aa;//1步最远可以到多远
        for (int i = 1; i < nums.size(); ++i){
            if (aa >= nums.size() - 1) return times;
            while (i < aa){
                bb = max(bb, nums[i] + i);
                ++i;
            }
            aa = max(bb,aa+nums[aa]);
            ++times;
        }
    }
};

这里的i<aa不能变成i<=aa。

这样++i可能直接就跳出循环了。

 

我的思路:

根据跳跃游戏1进行判断,同时不断更新dp数组,数组内记录着最少的步数

还是会超时。

class Solution {
public:
    int jump(vector<int>& nums) {
        int* dp=new int[nums.size()]();
        int reach=0;
        bool* flag=new bool[nums.size()]();
        for(int i=0;i<nums.size();i++)
        {
            int tmp=i+1;
            while(tmp<=i+nums[i]&&tmp<=nums.size()-1){
                if(flag[tmp]==0)
                    dp[tmp]=dp[i]+1;
                else
                    dp[tmp]=min(dp[i]+1,dp[tmp]);
                flag[tmp]=1;
                tmp++;
            }
            reach=max(reach,i+nums[i]);
            if(reach<=i&&reach!=nums.size()-1)
                return 0;
        }
        return dp[nums.size()-1];
    }
};

 

优化了一下:

还是剩一个超时:

class Solution {
public:
    int jump(vector<int>& nums) {
        int* dp=new int[nums.size()]();
        int reach=0;
        bool* flag=new bool[nums.size()]();
        for(int i=0;i<nums.size();i++)
        {
            int tmp=i+1;
            while(tmp<=i+nums[i]){
                if(flag[tmp]==0)
                    dp[tmp]=dp[i]+1;
                flag[tmp]=1;
                if(tmp==nums.size()-1)//贪心的思想,最先到达这里的肯定是最快的
                    return dp[tmp];
                tmp++;
            }
            reach=max(reach,i+nums[i]);
            if(reach<=i&&reach!=nums.size()-1)
                return 0;
        }
        return dp[nums.size()-1];
    }
};

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值