注:个人算法比较菜,由于是第一遍刷题,代码质量可能都不好,这里暂时做个刷题记录:)。
问题描述:
给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个位置。
示例 1:
输入: [2,3,1,1,4]
输出: true
解释: 我们可以先跳 1 步,从位置 0 到达 位置 1, 然后再从位置 1 跳 3 步到达最后一个位置。
示例 2:
输入: [3,2,1,0,4]
输出: false
解释: 无论怎样,你总会到达索引为 3 的位置。但该位置的最大跳跃长度是 0 , 所以你永远不可能到达最后一个位置。
作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/top-interview-questions-medium/xvb8zs/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
分析:
最优子结构:
1、倒数第i个可以直达
2、倒数第i个不可以直达
边界:
i =0 || i=1
状态转移方程式:
倒数第i个可以直达
arr[i]>=len-1-i
f(i)=f(i-1) //自顶向下迭代
倒数第i个不可直达
arr[i]<len-1-i
g(i)=g(i-1) //自顶向下迭代
代码求解:
1、递归方式求解
/** * @param {number[]} nums * @return {boolean} */ var canJump1 = function(nums) { if(nums.length===0) return false; //传入的数组为空,则返回false if(nums.length===1) return true; //数组只有一个元素,返回true var len = nums.length; if(nums[len-2]>=1){//若倒数第一个可以到达最后位置,则问题转化成长度为len-1的数组是否可以达到最后位置 return canJump1(nums.slice(0, len-1)); }else{//判断倒数第二个能否直达 for(var i=len-3; i>=0; i--){ if(nums[i]>=len-1-i){ if(i===0) return true; return canJump1(nums.slice(0, i+1)); } } return false; } };
经测试性能不过关,数组长度为10000个会报内存溢出错误。
2、采用自顶向下的方式求解。
var canJump = function(nums){ if(nums.length===0) return false; if(nums.length===1) return true; var len = nums.length; var index = len-1; //记住能够直达目标位置的数组索引 var max = len-1; //记住当前的要到达的目标位置 for(var i=len-1; i>=0; i--) {//自顶向下迭代 if(nums[i]>=max-i){//从i到max可达 index = i; max = i; } } return index===0; //如果第一个元素能到达目标位置,则最后位置是可达的 };
之前看过挖金矿问题的动态规划求解是自底向上的方式,本题没试过是否可行。后续再看看:)