前端刷题路-Day69:跳跃游戏(题号55)| 8月更文挑战

507 阅读1分钟

跳跃游戏(题号55)

题目

给定一个非负整数数组 nums ,你最初位于数组的 第一个下标

数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个下标。

示例 1

输入:nums = [2,3,1,1,4]
输出:true
解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 13 步到达最后一个下标。

示例 2

输入:nums = [3,2,1,0,4]
输出:false
解释:无论怎样,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 , 所以永远不可能到达最后一个下标。

提示:

  • 1 <= nums.length <= 3 * 104
  • 0 <= nums[i] <= 105

链接

leetcode-cn.com/problems/ju…

解释

这波啊,这波是经典贪心。

由于是中等题,笔者第一时间给想复杂了,以为又是那种有经典递归和DP两种结局方案的题。

虽然题目规定数组长度有10 ^ 4,但笔者依然是尝试了一下递归,不过这次失败得比较早,在第75个用例上GG了。

之后仔细想了想,其实题目没有那么复杂,问题的是能不能走到最后,而不是有几种方法能走到最后,那就简单很多了。

比方说当前的位置是i,那么当前位置可以达到的最远位置就是i + nums[i],当前位置加上当前可走的最大长度就是当前位置的最远位置。

知道这一点之后就一目了然了,每次循环更新一个最大位置,如果当前的i和最大元素相等或者比最大元素大,那就证明走到尽头了,一步也迈不出去。

或者说当前的最大位置已经超过数组的最大indexnums.length - 1),那就证明可以走到最后了,后面的都不用看了,直接返回就行。

自己的答案(递归)

十分简单的递归,也十分简单的失败了。

var canJump = function(nums) {
  var res = false
  function DFS(index) {
    if (index === nums.length - 1) return res = true
    if (res || (index >= nums.length)) return;
    for (let i = 1; i <= nums[index]; i++) {
      DFS(index + i)     
    }
  }
  DFS(0)
  return res
};

递归函数中先是两个终止条件,如果当前的index到了数组末尾,直接返回,否则如果restrue,也就是前面已经有位置可以走到最后了,也返回,如果当前的index已经比可以跳的位置更大,直接GG。

自己的答案(贪心)

思路上面说过了,先看看官方的答案👇:

var canJump = function(nums) {
  var n = nums.length
      rightmost = 0
  for (let i = 0; i < n; i++) {
    if (i <= rightmost) {
      rightmost = Math.max(rightmost, i + nums[i])
      if (rightmost >= n - 1) {
        return true
      }
    }
  }
  return false 
};

官方并没有给出JavaScript的答案,👆的答案是笔者根据C++的答案翻译过来的。

再看看笔者自己的答案👇:

var canJump = function(nums) {
  var maxLength = 0
      len = nums.length
  for (let i = 0; i < len; i++) {
    maxLength = Math.max(maxLength, i + nums[i])
    if (maxLength >= len - 1) return true
    if (maxLength <= i) return false
  } 
};

笔者这里的思路和官方有点不一样,但哪种比较好也不好说。

官方这里在遇到终止的情况之后就不进行任何赋值操作了,直接让后序的for循环走完,笔者这里给了剪枝操作,如果遇到没法再跳的情况下,直接return false

这一块感觉比官方好些,因为在没有找到答案之前,笔者的答案和官方答案都需要进行这两个判断:

maxLength <= i
maxLength >= len - 1

并且都需要利用Math.max()来给maxLength赋值,本质上是没有差别的。

从实际执行情况来说也确实好些,可以说是一种优化吧。

当然了,这题也可以使用DP来解决,不过有点过于复杂了,而且性能方面也不是很好,这里不推荐。

更好的方法



PS:想查看往期文章和题目可以点击下面的链接:

这里是按照日期分类的👇

前端刷题路-目录(日期分类)

经过有些朋友的提醒,感觉也应该按照题型分类
这里是按照题型分类的👇

前端刷题路-目录(题型分类)