[leetcode]Jump Game

本文深入解析了一种称为“跳跃游戏”的算法问题,探讨了如何判断能否从数组的起始位置达到末尾。通过分析,提出了两种解决方案:一是递归方法,但由于其复杂度高而超时;二是改进的贪心策略,通过每次选择能覆盖最多后续元素的跳跃点,有效解决了问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载请注明出处:http://www.cnblogs.com/StartoverX/p/4611518.html 

题目:

Given an array of non-negative integers, you are initially positioned at the first index of the array.

Each element in the array represents your maximum jump length at that position.

Determine if you are able to reach the last index.

For example:
A = [2,3,1,1,4], return true.

A = [3,2,1,0,4], return false.

 

分析:

初次尝试:

可以明显看出,在选择了第一个跳跃距离后,在下一个位置上,又回到了同样的问题,是一个具有子结构的问题,可以用递归的方法:

遍历每一次选择,继续在新位置上遍历每一个能够跳跃的点。

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

 很明显题目没有那么简单,得到了一个超时Time Limit Exceed。

继续分析,我们的最终目标是跳跃至最后一个位置,所以,在选择每一个跳跃距离的时候,应该使得下一次跳跃加上本次跳跃所能够覆盖的数字越多越好,例如:

      a1      a2     a3     a4  |    a5    a6    a7    a8

如果从a1开始选择并且a1 = 3,也就是能够跳跃的最远距离是a4,到分隔符为止。要使得下一次的选择更多,我们要保证下一次跳跃能够覆盖的分隔符后的数字更多。

也就是说,本次跳跃的选择应该是在a2-2,a3-1,a4三个数字中取最大值,如果a2-2最大,则跳至a2,a3-1最大,则跳至a3,a4最大则跳至a4。

也就是每次跳跃都应该选择跳跃范围内的点值减去与最远点间距离剩余值最大的点,这样,我们便找出了一个每次跳跃的贪心策略,可以到达最远的点。如果到达的点值为0且不是最后一个点,则无法继续推进,返回false。

class Solution {
public:
    bool canJump(vector<int>& nums) {
        if(nums.size() == 1 || nums.size() == 0)
        {
            return true;
        }
        int pos = 0;
        int init = nums[pos];
        while(1)
        {
            if(init == 0 && pos != nums.size()-1)//如果到达的点值为0,但不是最后一个点,则无法前进。
            {
                return false;
            }
            if(init >= nums.size() - 1 -pos)//如果到达的点值大于剩下的距离,则可以到达。
            {
                return true;
            }
            int max = -1;
            int next_pos = -1;
            for(int i=1;i<=init;i++)//选出分隔符后能到达最长的下一个点。
            {
                if(nums[pos+i]-(init-i) >= max)
                {
                    max = nums[pos+i]-(init - i);
                    next_pos = pos + i;
                }
            }
            pos = next_pos;
            init = nums[pos];
        }
    }
};

 

转载于:https://www.cnblogs.com/StartoverX/p/4611518.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值