1.跳跃游戏

思路1:
构建boolean数组
遍历nums,遍历到索引i时,
我们对i之前的位置进行遍历,比如存在这样的位置j(0<=j满足boolean数组[j]为true而且j+nums[j]>=i
则说明i位置可以到达,即设置boolean数组[i]=true
遍历nums结束后
我们返回boolean数组的最后一个元素即可,false则不可到达,true则可以到达
public boolean canJump(int[] nums) {int n=nums.length;boolean[] b=new boolean[n];Arrays.fill(b,false);if(n==1){//当只有一个元素时,无论如何都会到达return true;}else{//当不只一个元素时且第一个元素为0时直接返回false,否则将第一个元素boolean设置为trueif(nums[0]>0){b[0]=true;}else{return false;}}int j=0;for(int i=1;i<n;i++){j=i-1;while(j>=0){if(nums[j]>=i-j&&b[j]){//核心判断条件b[i]=true;break;}j--;}}return b[n-1];}
思路2:
遍历数组nums
维护一个变量max,表示最远到达的位置
如果当前i在max范围内,则将max更新为i+nums[i]和max的最大值
遍历结束后判断max是否大于或等于n-1,n为数组长度
true则可以到达,false则不行
public boolean canJump(int[] nums) {int n=nums.length;int max=0;for(int i=0;i<n;i++){if(i<=max){max=Math.max(max,i+nums[i]);}}return max>=n-1;}
上面非得全部遍历一遍才return
可以在循环的时候就进行提前return
class Solution {public boolean canJump(int[] nums) {int n=nums.length;int max=0;for(int i=0;i<n;i++){if(i<=max){max=Math.max(max,i+nums[i]);if(max>=n-1){return true;}}}return false;}
疑惑:
为什么思路2是贪心算法?
2.跳跃游戏II

思路1:
本题有一个假设 :即给出的用例是一定可以到达数组最后一个位置
这个假设也是官方题解的大前提
遍历nums
更新最远到达距离和边界
我们用最远到达距离来更新边界
即当i等于边界时,
边界=最远到达距离
class Solution {public int jump(int[] nums) {int end = 0;int maxPosition = 0;int steps = 0;for(int i = 0; i < nums.length - 1; i++){//找能跳的最远的maxPosition = Math.max(maxPosition, nums[i] + i);if( i == end){ //遇到边界,就更新边界,并且步数加一end = maxPosition;steps++;}}return steps;
由于题目的假设,所以我们完全不需要考虑能不能到达最后一个位置
即循环结束后的maxPosition是一定大于或等于n-1
注意这里i
比如【1,2】
如果用i<nums.length,则会进入if条件两次,其实只需要一次即可
疑惑:
这道题如果没有该假设,那这样写根本不行
看评论里说华为的类似笔试题只能对50%,我觉得应该是华为没有相关假设
怎么确保过程中的边界可以跳跃到??
边界就是范围的最大值,并不是是说跳跃的时候一定要正好经过边界
即在这个范围内必须跳一次,至于具体哪个位置就不管了
如果不跳后面无法进行
比如从2开始,第一个边界是0+2,当i遍历到索引2时,最晚这个时候就得跳了,否则后面无法继续;
要是这么理解感觉这道题
