1 题目
题目:跳跃游戏II(Jump Game II)
描述:给出一个非负整数数组,你最初定位在数组的第一个位置。数组中的每个元素代表你在那个位置可以跳跃的最大长度。你的目标是使用最少的跳跃次数到达数组的最后一个位置,返回最少的跳跃次数值。
lintcode题号——117,难度——medium
样例1:
输入:A = [2,3,1,1,4]
输出:2
解释:到达最后位置的最小跳跃次数是2(从下标0到1跳跃1个距离长度,然后跳跃3个距离长度到最后位置)
2 解决方案
2.1 思路
使用动态规划的方式解,将状态定义为表示跳到第i个位置需要的最少次数,则在能从j一次跳到i的情况下,跳到i的最少次数 = min(跳动j的最少次数 + 1,上次记录的跳到i的最优值),理清动态规划的四要素即可解出。
2.2 时间复杂度
本题动态规划的多重循环是对同一维的下标进行的,相当于在一个耗时n的循环内嵌套了同为耗时n的循环,时间复杂度为O(n^2)。
2.3 空间复杂度
使用了容量为n的数组,空间复杂度为O(n)。
3 源码
细节:
- 动态规划的四要素:状态、方程、初始化、答案。(四要素在之前的题目数字三角形1中有详细介绍)
- 状态:用
dp[i]
表示跳到第i个位置需要的最少次数。 - 方程:在能从j一次跳到i的情况下(
dp[j] != INT_MAX && A[j] + j >= i
),跳到i的最少次数 = min(跳动j的最少次数 + 1,上次记录的跳动i的最优值)
。 - 初始化:
dp[0] = 0
,从起点出发,跳到起点需要0次。 - 答案:跳到最后一个位置的最少次数,即
dp[max]
。
C++版本:
/**
* @param A: A list of integers
* @return: An integer
*/
int jump(vector<int> &A) {
// write your code here
if (A.empty())
{
return 0;
}
// 状态:dp[i]表示跳到第i个位置需要的最少次数
vector<int> dp(A.size(), INT_MAX);
// 初始化:从起点出发,跳到起点需要0次
dp[0] = 0;
for (int i = 1; i < dp.size(); i++)
{
for (int j = 0; j < i; j++)
{
// 方程:在能从j一次跳到i的情况下,跳到i的最少次数 = min(跳动j的最少次数 + 1,上次记录的跳动i的最优值)
if (dp[j] != INT_MAX && A[j] + j >= i)
{
dp[i] = min(dp[j] + 1, dp[i]);
}
}
}
return dp[dp.size() - 1]; // 答案:跳到最后一个位置的最少次数
}
数字三角形:https://blog.youkuaiyun.com/SeeDoubleU/article/details/124678103 ↩︎