跳跃游戏
给出一个非负整数数组,你最初定位在数组的第一个位置。
数组中的每个元素代表你在那个位置可以跳跃的最大长度。
判断你是否能到达数组的最后一个位置。
样例
A = [2,3,1,1,4],返回 true.
A = [3,2,1,0,4],返回 false.
注意
这个问题有两个方法,一个是贪心和 动态规划。
贪心方法时间复杂度为O(N)。
动态规划方法的时间复杂度为为O(n^2)。
我们手动设置小型数据集,使大家阔以通过测试的两种方式。这仅仅是为了让大家学会如何使用动态规划的方式解决此问题。如果您用动态规划的方式完成它,你可以尝试贪心法,以使其再次通过一次。
Solution:
方法一.动态规划求解
首先来看一下如何使用动态规划求解该问题。使用动态规划求解问题,首先需要找到问题的状态和状态转化方程
假设问题的状态,假设位置
i(0≤i≤A.length)
能够跳跃的最大长度为dp[i]。
对于数组A = [2,3,1,1,4], 则有:
i = 0, dp[0] = A[0] + 0 = 2
i = 1, if dp[i-1] = dp[0]
≥
i then dp[1] =
max{A[1]+1,dp[0]}=4
else dp[1] = 0
i = 2, if dp[i-1] = dp[1]
≥
i then dp[2] =
max{A[2]+2,dp[1]}
= 4 else dp[2] = 0
基于上面的分析,其状态转换方程为:
dp[i]={max{A[i]+i,dp[i−1]},0,if dp[i−1]≥iotherwise
注意:需要判断能否到达第
i
个位置
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
方法二:贪心算法
如果对上面的代码认真分析以下的话,是没有必要创建dp数组的,可以使用一个变量来进行替换。及
currMaxStep
用来记录从0到第
i
个位置中所能跳到最远的距离。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
跳跃游戏 II
给出一个非负整数数组,你最初定位在数组的第一个位置。
数组中的每个元素代表你在那个位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。
样例
给出数组A = [2,3,1,1,4],最少到达数组最后一个位置的跳跃次数是2(从数组下标0跳一步到数组下标1,然后跳3步到数组的最后一个位置,一共跳跃2次)
方法一:动态规划求解
首先,假设问题的状态:“假设跳到数组第
i(0≤i≤A.length−1)
个位置,需要使用的最少次数为
dp[i]
”。
对于数组 A = [2,3,1,1,4], 有:
i=0,dp[0]=0
(开始就在第一个位置)
i=1,{2},dp[1]=1
i=2,{2,3},dp[2]=min(dp[0]+1,dp[1]+1)=1
i=3,{2∗,3,1},dp[3]=min(dp[1]+1,dp[2]+1)=2
因此,转态转换方程为:
dp[i]=min{dp[j]+1}
and
j+A[j]≥i
, for
0≤j≤i−1
Talk is cheap, show me the code !
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
这是我用python2实现的,逻辑应该没问题但是过不了计蒜客的oj
# -*-coding:utf-8 -*-
def dp(arr,num):
count= [999]*num #保存跳跃次数
count[0] = 0
# print(len(dp))
if num <= 1:
return 0
for i in xrange(1,len(arr)):
for j in xrange(i):
if arr[j] +j >= i:
count[i] = min(count[i],count[j]+1)
return count[num-1]
num = int(raw_input())
arr = map(int,raw_input().split(' '))
print(dp(arr,num))
时间复杂度 O(n2) , 空间复杂度 O(n)
方法二:贪心算法
如果这代码放在LeetCode上运行是会超时的。与Jump Code I 一样这题也是可以使用贪心算法来进行求解的。。 该代码和思路来自 LeetCode discuss
其主要是基于贪心的思想。假设当前(位置i)能够跳最远的范围为[curBegin, curEnd], curFarther是在[curBegin, curEnd]范围内能够跳的最远距离(位置)。一旦当前位置(i)到了curEnd, 那么就会触发一次跳跃,并且设置curEnd等于curFarthest。按照上面的步骤,直到跳跃到最后一个位置为止。其代码为:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
时间复杂度 O(n) ,空间复杂度 O(1)
方法三: BFS
LeetCode Discuss 上提出了BFS方法
其实可以把这个为题转换为BFS问题(注:如果认真思考一下的话, 可以看成单源最短路径问题)。及第 i 层所有的节点都能够在 i−1 步下到达。例如 2 3 1 1 4 ==> 2 || 3 1 || 1 4 ||
代码为:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
时间复杂度 O(n) , 空间复杂度 O(1)