Every day a Leetcode
题目来源:55. 跳跃游戏
解法1:动态规划
用 n 表示数组 nums 的长度。初始时位于下标 0,需要判断是否可以到达下标 n−1。
设 dp[i] 表示从下标范围 [0,i] 中的任意下标出发可以到达的最大下标。
对于 1≤i<n,如果可以从下标 0 到达下标 i,则可以从下标 i 到达不超过下标 i+nums[i] 的任意位置,因此可以从下标 0 到达不超过下标 i+nums[i] 的任意位置。为了判断是否可以到达下标 n−1,需要分别计算从每个下标出发可以到达的最大下标。
对于每个下标,需要首先判断是否可以从更小的下标到达该下标,然后计算从该下标出发可以到达的最大下标。
代码:
class Solution
{
public:
bool canJump(vector<int> &nums)
{
int n = nums.size();
// dp[i] 表示从下标范围 [0,i] 中的任意下标出发可以到达的最大下标
vector<int> dp(n);
// 初始化
dp[0] = nums[0];
// 状态转移
for (int i = 1; i < n; i++)
{
if (dp[i - 1] < i)
return false;
dp[i] = max(dp[i - 1], i + nums[i]);
}
return dp[n - 1] >= n - 1;
}
};
结果:
复杂度分析:
时间复杂度:O(n),其中 n 是数组 nums 的长度。
空间复杂度:O(n),其中 n 是数组 nums 的长度。
解法2:贪心
遍历数组 nums 的每一个元素,更新能跳到的最远值 max_far = max(max_far, i + nums[i]),只要 max_far >= n - 1,即可返回 true。
代码:
class Solution
{
public:
bool canJump(vector<int> &nums)
{
int n = nums.size();
int max_far = 0; // 目前能跳到的最远位置
for (int i = 0; i < n; i++)
{
if (i <= max_far)
{
max_far = max(max_far, i + nums[i]);
if (max_far >= n - 1)
return true;
}
}
return false;
}
};
结果:
复杂度分析:
时间复杂度:O(n),其中 n 是数组 nums 的长度。
空间复杂度:O(1)。