55.跳跃游戏 I
算法思路
我们的目标就是看每次的数字加上自身的位置是否能够到达最后的位置,可以通过贪心算法来进行求解。
首先我们分析一下整体的过程,我们就是从每一个位置跳,如果能跳到最后的位置,那就说明可以到。我们就直接计算每一个位置能够跳的最远的距离,记录下来,之后全局来看最远的距离是不是能够到最后的位置或者超过最后的位置即可。主要分两部分:
- 首先要看能不能跳到下一个位置
- 其次记录每个位置能到的最远距离
代码
class Solution {
public boolean canJump(int[] nums) {
if(nums.length <= 1) return true;
int maxRight = 0;
for(int i = 0;i<nums.length;i++){
if(maxRight < i)return false;
maxRight = Math.max(maxRight,i+nums[i]);
}
return true;
// for(int i = 0;i<=maxRight;i++){
// maxRight =Math.max(maxRight, i + nums[i]);
// if(maxRight >= nums.length-1)
// return true;
// }
// return false;
}
}
复杂度
时间度杂度:O(N),一次循环
空间复杂度:O(1),没有额外开辟空间
45.跳跃游戏 II
本题和上题有点类似,前面一提判断一个数组的最后一个数是否可达,而这一题判断在可达最后一个数的前提下 最少的次数。
算法思路
使用贪心算法,通过局部最优来实现全局最优。而本题可以通过两种贪心来求解,一个是从最后开始,一个从开头开始。
这里只讨论复杂度最优的方法,正向查找最优解。
- 首先需要一个变量end来记录当前能够跳跃的边界,每次循环记录所能到达的最远距离maxRight;
- 当前能够到达的最大下标位置,记为边界end。我们从左到右遍历数组,到达边界时,更新边界并将跳跃次数增加 1;
- 在遍历数组时,我们不访问最后一个元素,这是因为在访问最后一个元素之前,我们的边界一定大于等于最后一个位置,否则就无法跳到最后一个位置了。如果访问最后一个元素,在边界正好为最后一个位置的情况下,我们会增加一次**「不必要的跳跃次数」**,因此我们不必访问最后一个元素。
class Solution {
public int jump(int[] nums) {
if(nums==null||nums.length == 1) return 0;
int step = 0,rightMax = 0,end = 0;
for(int i = 0;i<nums.length-1;i++){
rightMax = Math.max(rightMax,nums[i]+i);
//if(rightMax >= nums.length -1) return step+1;
if(i == end){
step++;
end = rightMax;
}
}
return step;
}
}
复杂度
时间复杂度:O(N),只进行了一个for循环
空间复杂度:O(1)