1 题目
题目:跳跃游戏(Jump Game)
描述:给出一个非负整数数组,你最初定位在数组的第一个位置。数组中的每个元素代表你在那个位置可以跳跃的最大长度。判断你是否能到达数组的最后一个位置。
lintcode题号——116,难度——medium
样例1:
输入:A = [2,3,1,1,4]
输出:true
解释:0 -> 1 -> 4(这里的数字为下标)是一种合理的方案。
样例2:
输入:A = [3,2,1,0,4]
输出:false
解释:不存在任何方案能够到达终点。
2 解决方案
2.1 思路
使用动态规划的方式解,将状态定义为表示是否能够走到位置i,则第i个位置可达的条件——第j个位置可达、且第j个位置上的数字加上j能够超过i,满足条件即可判断第i个位置可达,理清动态规划的四要素即可解出。
2.2 时间复杂度
本题动态规划的多重循环是对同一维的下标进行的,相当于在一个耗时n的循环内嵌套了同为耗时n的循环,时间复杂度为O(n^2)。
2.3 空间复杂度
使用了容量为n的数组,空间复杂度为O(n)。
3 源码
细节:
- 动态规划的四要素:状态、方程、初始化、答案。(四要素在之前的题目数字三角形1中有详细介绍)
- 状态:用
dp[i]
表示是否能够走到位置i。 - 方程:第i个位置可达的条件——第j个位置可达、且第j个位置上的数字加上j能够超过i,满足条件即可判断
dp[i] = true
- 初始化:
dp[0] = true
,起点是第一个位置,所以可以到达。 - 答案:最后一个位置是否可达,即
dp[max]
。
C++版本:
/**
* @param A: A list of integers
* @return: A boolean
*/
bool canJump(vector<int> &A) {
// write your code here
if (A.empty())
{
return true;
}
// 状态:dp[i]表示是否能够走到位置i
vector<int> dp(A.size(), false);
// 初始化:起点是第一个位置,所以可以到达
dp[0] = true;
for (int i = 0; i < dp.size(); i++)
{
for (int j = 0; j < i; j++)
{
// 方程:第i个位置可达的条件——第j个位置可达、且第j个位置上的数字加上j能够超过i
if (dp[j] == true && A[j] + j >= i)
{
dp[i] = true;
}
}
}
return dp[dp.size() - 1]; // 答案:最后一个位置是否可达
}
数字三角形:https://blog.csdn.net/SeeDoubleU/article/details/124678103 ↩︎