当前位置:   article > 正文

55.跳跃游戏_给定一个整数数组,表示位于直线上的障碍物的坐标。 假设您从坐标为 0的点向右跳。

给定一个整数数组,表示位于直线上的障碍物的坐标。 假设您从坐标为 0的点向右跳。

中等

给定一个非负整数数组,你最初位于数组的第一个位置。

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

判断你是否能够到达最后一个位置。

示例 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/problems/jump-game
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


解法1:top to bottom的动态规划:

用一个表,存储每个位置的通路情况,初始状态都是未知的状态0,只有终点位置是1.

有一种递归的思想。

首先jump(0)检查位置0的点,它可以去到位置1,2,3.我们依次检查三个子节点。

    检查位置1,jump(1).它可以去到位置2.

         检查位置2,jump(2).遍历完后发现,没有通路,更新位置2的通路状态=-1,返回false到jump(1).

    位置1遍历结束,jump(1)完成,没有通路,更新位置1的通路状态=-1,返回false到jump(0).

jump(0)继续遍历jump(2),因为2的通路状态是-1,所以返回false到jump(0).

jump(0)继续遍历jump(3).位置3可以去到位置4或者位置5,位置5越界所以排除。

    jump(3)遍历jump(4),jump(4)的通路状态为1,所以返回true.到jump(3).

jump(3)返回true到jump(0).

jump(0)再返回true.

此时说明从0点可以找到通路到最后。

代码实现

  1. /**
  2. * @param {number[]} nums
  3. * @return {boolean}
  4. */
  5. var canJump = function(nums) {
  6. const totalLength = nums.length
  7. const memo = Array(totalLength).fill(0) //记录每个点的通路状态
  8. memo[totalLength-1] = 1 //终点必然是通的
  9. function jump(position) {
  10. if(memo[position] === 1) {
  11. return true
  12. }else if(memo[position] === -1) {
  13. return false
  14. }
  15. //从当前点最多可以跳到哪个位置,不能越界
  16. const maxJump = Math.min(position + nums[position], totalLength-1)
  17. for (let i = position+1; i <= maxJump; i++) {
  18. let jumpResult = jump(i)
  19. if (jumpResult === true) {
  20. memo[position] = 1 //这里是position哦,因为子路通了
  21. return true
  22. }
  23. }
  24. //遍历所有可能的通路都没发现,更新位置i通路状态,返回false.
  25. memo[position] = -1
  26. return false
  27. }
  28. let result = jump(0)
  29. return result
  30. };

解法2:

从后向前找。

将最后一个位置通路状态标位1,其他位置都为0。

从倒数第二个位置开始,依次向前找。

  位置3,可以到达位置4,状态更新为1。

  位置2,到不了3或者4,状态更新为-1。

  位置1,到不了3或者4,状态更新为-1。

  位置0,可以到3,状态更新为1.

返回位置0的道路状态值。

代码实现

  1. /**
  2. * @param {number[]} nums
  3. * @return {boolean}
  4. */
  5. var canJump = function(nums) {
  6. const totalLength = nums.length
  7. const memo = Array(totalLength).fill(0)
  8. memo[totalLength-1] = 1
  9. for(let position = totalLength-2; position >= 0; position--){ //从倒数第二位开始检查
  10. let maxJump = Math.min(position + nums[position], totalLength-1)
  11. for (let j = position+1; j <= maxJump; j++) { //检查可以到的点,有没有通的
  12. if (memo[j] === 1) {
  13. memo[position] = 1 //找到1个,修改当前点状态
  14. break
  15. }
  16. }
  17. }
  18. if(memo[0] === 1) {
  19. return true
  20. }else {
  21. return false
  22. }
  23. };

贪心算法 

就和上面一个思路很像,不过是用一个变量存储当前可行的节点

从倒数第二位置开始遍历

  位置3+步长>maxJump,可以跳到最后一个位置,这是个优位置,将maxJump更新为位置3

  位置2,不能跳到maxJump,看下一个

  位置1,不能跳到maxJump,看下一个

  位置0+步长 >= maxJump, 可以跳到maxJump,更新maxJump = 0

返回maxJump是否等于0,等于0则是存在通路的

代码实现

  1. /**
  2. * @param {number[]} nums
  3. * @return {boolean}
  4. */
  5. var canJump = function(nums) {
  6. const totalLength = nums.length
  7. let maxJump = totalLength - 1 //初始值设为最后一个位置
  8. for(let i = totalLength-2; i>=0; i--) {
  9. if(i+nums[i] >= maxJump) { //能不能跳过一个优位置
  10. maxJump = i //将现在位置标为一个优位置
  11. }
  12. }
  13. // if (maxJump === 0) {
  14. // return true
  15. // }else {
  16. // return false
  17. // }
  18. return maxJump === 0 //这样写更简洁
  19. };

最快的是贪心,其次是bottom2top,最慢的是top2bottom,因为有递归

复习:

9.13:第一种方法有点深度优先遍历。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/622270
推荐阅读
相关标签
  

闽ICP备14008679号