题目描述
https://leetcode-cn.com/problems/jump-game/
解法
思考使用dp来做的话,我们的dp数组定义为什么?
- 变量是什么?每步跳跃,抵达的位置不同,每个位置能跳的步数也不同,我们如何定义dp?
- 很明显我们用dp来表达每个位置能跳的步数,所以我们只能选择抵达的位置,于是得出dp[i]表示从0到i下标是否可以抵达
- 思考递推,当前的dp[i]取决于之前的从之前的位置出发是否能抵达,我们需要维护一个变量来表示当前能抵达的最大下标,如果当前的下标在最大能抵达下标范围内(因为可以跳1步),则为true,于是更新max
- 边界就是dp[0] = true;
- 编写代码
class Solution {
public boolean canJump(int[] nums) {
boolean []dp = new boolean[nums.length];//表示从0到下标i的是否可以到达
dp[0]=true;
int max = 0+nums[0];//当前能抵达的最大下标
for(int i=1;i<nums.length;i++){
if(max>=i){
dp[i] = true;
if(nums[i]+i>max)
max = nums[i]+i;//更新能抵达的最大下标
}
//else dp[i] = false;//不能抵达
}
return dp[nums.length-1];
}
}
根据dp使用,可以优化空间复杂度:
class Solution {
public boolean canJump(int[] nums) {
//boolean []dp = new boolean[nums.length];//表示从0到下标i的是否可以到达
boolean res = true;//dp[0]等于true
int max = 0+nums[0];//当前能抵达的最大下标
for(int i=1;i<nums.length;i++){
if(max>=i){
res = true;
if(nums[i]+i>max)
max = nums[i]+i;//更新能抵达的最大下标
}else
res = false;
}
return res;
}
}
如果使用贪心算法呢?
转化问题:请问通过题目中的跳跃规则,最多能跳多远?如果能够越过最后一格,返回 true,否则返回 false。
于是我们可以写出如下贪心代码:
int n = nums.length;
int farthest = 0;
for (int i = 0; i < n - 1; i++) {
// 不断计算能跳到的最远距离
farthest = max(farthest, i + nums[i]);
// 可能碰到了 0,卡住跳不动了
if (farthest <= i) return false;
}
return farthest >= n - 1;
发现和上面的代码差不多,我们是否可以思考以下贪心和动态规划的区别呢?