[Leetcode]Jump Game && Jump Game II

本文探讨了两种跳跃算法问题:一是判断能否到达数组末尾,二是求解到达末尾所需的最少跳跃次数。通过两种不同的贪心算法实现,介绍了具体的实现思路与代码示例。

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

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.

这道题拿过来就“呵呵”了两次,一次用的递归timeout,一次用的DP又是timeout。这里倒不是说DP不能用,可能是我的DP写的效率太低了。最后用贪心实现了算法。(话说贪心和DP有千丝万缕的联系啊,为什么DP不行呢?唉...)

这里从第一步开始,都用一个量farest存储当前所能到达的最远处,贪心选择就是:如果当前位置i+A[i]>farest更新farest,直到farest>=n-1结束。

然后考虑失败的情况,失败的前提肯定是第i个数组元素为零,并且前i-1个元素所能到达的最远位置就是i,那么游戏结束,返回false。

上代码:

class Solution{
public:
	bool canJump(int A[], int n) {
		int farest = 0;
		for (int i = 0; i < n; i++){
			if (i == farest && A[i] == 0) break;
			if (A[i] + i > farest){
				farest = A[i] + i;
			}
			if (farest >= n - 1)
				return true;
		}
		if (farest == n - 1) return true;
		else return false;
	}
};

后来在网上翻了一下别人的做法,还有另一种贪心的实现方式,就是用一个量来记录当前位置可跳的最大步数。

从maxstep =  A[0]开始,当i=1时,maxstep--,然后和A[1]比较,不断更新maxstep,直到游戏结束。

class Solution {  
public:  
    bool canJump(int A[], int n) {  
        if(n==0||n==1){  
            return true;  
        }  
        int maxstep=A[0];  
        for(int i=1;i<n;i++){  
            if(maxstep==0) return false;  
            maxstep--;  
            if(maxstep<A[i]){  
                maxstep=A[i];  
            }  
            if(maxstep+i>=n-1){  
                return true;  
            }  
        }  
    }  
}; 

再看第二题

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.

Your goal is to reach the last index in the minimum number of jumps.

For example:
Given array A = [2,3,1,1,4]

The minimum number of jumps to reach the last index is 2. (Jump 1 step from index 0 to 1, then 3 steps to the last index.)

这一题是要找到到达n的最小步数。这里仍然使用贪心的思想,在第一题的基础上,记录每一步可以到达的最远距离。

例如第一步,可到达的最远距离是A[0],这是还没到达n,所以就要再走第二步,那么就在1-A[i]之间,找到可以到达最远距离的第二步,作为第二步,局部最佳就是全局最佳,最后得到最小步数。

class Solution {
public:
	int jump(int A[], int n) {
		if (0 == n || 1 == n || A[0] == 0) return 0;
		if (A[0] >= n-1) return 1;
		return nextStep(0, A[0], n, 1, A);
	}
	int nextStep(int start, int end, int n, int steps,int A[]){
		int newEnd = end;
		int newStart;
		for (int i = start; i <= end; i++){
			if (i + A[i] > newEnd){
				newEnd = i + A[i];
				newStart = i;
			}
			if (newEnd >= n - 1)
				return ++steps;
		}
		return nextStep(newStart, newEnd, n, ++steps, A);
	}
};
下面来一个非递归的实现:

用last记录上一步到达过的最远距离,只要i超过这个位置,step就得加一,并且更新last的值。

class Solution {  
public:  
    int jump(int A[], int n) {  
        int ret = 0;//当前跳数  
        int last = 0;//上一跳可达最远距离  
        int curr = 0;//当前一跳可达最远距  
        for (int i = 0; i < n; ++i) {  
            if(i>curr){  
                return -1;  
            }  
            if (i > last) {  
                last = curr;  
                ++ret;  
            }   
            curr = max(curr, i+A[i]);  
        }  
  
        return ret;  
    }  
}; 





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值