0
点赞
收藏
分享

微信扫一扫

[动态规划]DP28 跳跃游戏(三)-中等

​​DP28 跳跃游戏(三)​​

描述

给定一个非负整数数组nums,假定最开始处于下标为0的位置,数组里面的每个元素代表下一跳能够跳跃的最大长度。请你判断最少跳几次能跳到数组最后一个位置。

1.如果跳不到数组最后一个位置或者无法跳跃(即数组长度为0),请返回-1

2.数据保证返回的结果不会超过整形范围,即不会超过


数据范围:

输入描述:

第一行输入一个正整数 n 表示数组 nums的长度

第二行输入 n 个整数,表示数组 nums 的内容

输出描述:

输出最少跳几次到最后一个位置

示例1

输入:

7
2 1 3 3 0 0 100

输出:

3

说明:

首先位于nums[0]=2,然后可以跳2步,到nums[2]=3的位置,step=1 再跳到nums[3]=3的位置,step=2再直接跳到nums[6]=100,可以跳到最后,step=3,返回3

示例2

输入:

7
2 1 3 2 0 0 100

输出:

-1

题解

贪心解法

假设数组长度为n:

  1. 如果n等于0,则可以直接返回-1
  2. 如果n等于1,则可以直接返回0
  3. 当n大于0的时候,走第一步最远可以到达v[0]的索引位置,当我们要走到v[0]+1的索引位置的时候应该要走第二步,假设正整数k属于在区间[0,i],那么当v[k]+k取最大值的时候,也就是我们第二步从索引为k的位置起跳可以到达最远的位置。依次类推,我们使用len表示走step步的时候可以到达的最远距离,然后当len <= i的时候,我们要走step+1步,此时选择[0,i]区间中能使v[k]+k取最大值的索引作为下一次起跳的位置,由于我们每次遍历的时候是可以计算每个v[i]+i的值得,因此我们可以使用一个计数器来存放该值

代码如下:

#include <bits/stdc++.h>

int solve(const std::vector<int> &v)
{
if (v.size() == 0)
{
return -1;
}

if (v.size() == 1)
{
return 0;
}
int len = v[0];// 走1步的时候可以最远到达的索引位置
int next = len;// 用于记录[0,v[0]+1]区间中v[k]+k的最大值
int step = 1; // 最少要走的步数
for (int i = 1; i < v.size() - 1; ++i)
{
if (len <= i)
{
len = std::max(next, v[i] + i);
step++;
}
else
{
next = std::max(next, v[i] + i);
}

if (len <= i)
{
return -1;
}
// 其实,这里可以判断len是否大于等于n-1,如果满足则可以跳出循环
}
return step;
}

int main()
{
int n;
std::cin >> n;
std::vector<int> v(n);
for (int i = 0; i < n; ++i)
{
std::cin >> v[i];
}

std::cout << solve(v) << std::endl;
return 0;
}

动态规划解法

  • 假设我们使用dp[i]表示到达索引i位置时的最少步数。
  • 初始条件:dp[k] = INT_MAX,dp[0] = 0,表示到达索引位置0的时候所走的步数
  • dp[i] = min(dp[k]+1),其中k满足v[k]+k >= i,0<=k<i

这个解法的时间复杂度为o(n^2),超时了~

int solve_2(const std::vector<int> &v)
{
if (v.size() == 0)
{
return -1;
}
std::vector<int> dp(v.size(), INT_MAX);
dp[0] = 0;
for (int i = 1; i < v.size(); ++i)
{
for (int k = i - 1; k >= 0; --k)
{
if (k + v[k] >= i)
{
dp[i] = std::min(dp[i], dp[k] + 1);
}
}

if (dp[i] == INT_MAX)
{
return -1;
}
}
return dp.back();
}


动态规划解法——二

嗯,另一种思路。我们可以将dp[i]定义为走i步的时候可以到达的最远距离。

  1. 初始条件:dp[0]=0,表示一开始走0步的时候在索引为0的位置,dp[1]=v[0]表示走1步可以到达的最远距离
  2. 递推条件:dp[i] = dp[i-1]+v[dp[i-1]],表示第i步在索引为dp[i-1]的位置开始,最多能走v[dp[i-1]]步
  3. 返回值:dp.size


举报

相关推荐

0 条评论