daily leetcode - jump-game - !

题目地址

https://leetcode.com/problems/jump-game/

题目描述

Given an array of non-negative integers, you are initially positioned at the first index of the array.

Each element in the array represents your maximum jump length at that position.

Determine if you are able to reach the last index.

Example 1:

Input: [2,3,1,1,4]
Output: true
Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last index.

Example 2:

Input: [3,2,1,0,4]
Output: false
Explanation: You will always arrive at index 3 no matter what. Its maximum
             jump length is 0, which makes it impossible to reach the last index.

思路

这道题说的是有一个非负整数的数组,每个数字表示在当前位置的最大跳力(这里的跳力指的是在当前位置为基础上能到达的最远位置),求判断能不能到达最后一个位置,开始博主以为是必须刚好到达最后一个位置,超过了不算,其实是理解题意有误,因为每个位置上的数字表示的是最大的跳力而不是像玩大富翁一样摇骰子摇出几一定要走几。这里可以用动态规划 Dynamic Programming 来解,维护一个一维数组 dp,其中 dp[i] 表示达到 i 位置时剩余的跳力,若到达某个位置时跳力为负了,说明无法到达该位置。接下来难点就是推导状态转移方程啦,想想啊,到达当前位置的剩余跳力跟什么有关呢,其实是跟上一个位置的剩余跳力(dp 值)和上一个位置新的跳力(nums 数组中的值)有关,这里新的跳力就是原数组中每个位置的数字,因为其代表了以当前位置为起点能到达的最远位置。所以当前位置的剩余跳力(dp 值)和当前位置新的跳力中的较大那个数决定了当前能到的最远距离,而下一个位置的剩余跳力(dp 值)就等于当前的这个较大值减去 1,因为需要花一个跳力到达下一个位置,所以就有状态转移方程了:dp[i] = max(dp[i - 1], nums[i - 1]) - 1,如果当某一个时刻 dp 数组的值为负了,说明无法抵达当前位置,则直接返回 false,最后循环结束后直接返回 true 即可,参见代码如下:

解法一:

class Solution {
public:
    bool canJump(vector<int>& nums) {
        vector<int> dp(nums.size(), 0);
        for (int i = 1; i < nums.size(); ++i) {
            dp[i] = max(dp[i - 1], nums[i - 1]) - 1;
            if (dp[i] < 0) return false;
        }
        return true;
    }
};

其实这题最好的解法不是 DP,而是贪婪算法 Greedy Algorithm,因为这里并不是很关心每一个位置上的剩余步数,而只希望知道能否到达末尾,也就是说我们只对最远能到达的位置感兴趣,所以维护一个变量 reach,表示最远能到达的位置,初始化为 0。遍历数组中每一个数字,如果当前坐标大于 reach 或者 reach 已经抵达最后一个位置则跳出循环,否则就更新 reach 的值为其和 i + nums[i] 中的较大值,其中 i + nums[i] 表示当前位置能到达的最大位置,参见代码如下:

解法二:

class Solution {
public:
    bool canJump(vector<int>& nums) {
        int n = nums.size(), reach = 0;
        for (int i = 0; i < n; ++i) {
            if (i > reach || reach >= n - 1) break;
            reach = max(reach, i + nums[i]);
        }
        return reach >= n - 1;
    }
};

思路 2

这道题目是一道典型的回溯类型题目。
思路就是用一个变量记录当前能够到达的最大的索引,我们逐个遍历数组中的元素去更新这个索引。
变量完成判断这个索引是否大于数组下表即可。

关键点解析

  • 建模 (记录和更新当前位置能够到达的最大的索引即可)

代码

  • 语言支持: JavaScript,Python3

/*
 * @lc app=leetcode id=55 lang=javascript
 *
 * [55] Jump Game
 *
 * https://leetcode.com/problems/jump-game/description/
 *
 * algorithms
 * Medium (31.38%)
 * Total Accepted:    252.4K
 * Total Submissions: 797.2K
 * Testcase Example:  '[2,3,1,1,4]'
 *
 * Given an array of non-negative integers, you are initially positioned at the
 * first index of the array.
 *
 * Each element in the array represents your maximum jump length at that
 * position.
 *
 * Determine if you are able to reach the last index.
 *
 * Example 1:
 *
 *
 * Input: [2,3,1,1,4]
 * Output: true
 * Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last
 * index.
 *
 *
 * Example 2:
 *
 *
 * Input: [3,2,1,0,4]
 * Output: false
 * Explanation: You will always arrive at index 3 no matter what. Its
 * maximum
 * jump length is 0, which makes it impossible to reach the last index.
 *
 *
 */
/**
 * @param {number[]} nums
 * @return {boolean}
 */
var canJump = function(nums) {
  let max = 0; // 能够走到的数组下标

  for(let i = 0; i < nums.length; i++) {
      if (max < i) return false; // 当前这一步都走不到,后面更走不到了
      max = Math.max(nums[i] + i, max);
  }

  return max >= nums.length - 1
};

Python3 Code:

class Solution:
    def canJump(self, nums: List[int]) -> bool:
        """思路同上"""
        _max = 0
        _len = len(nums)
        for i in range(_len-1):
            if _max < i:
                return False
            _max = max(_max, nums[i] + i)
            # 下面这个判断可有可无,但提交的时候数据会好看点
            if _max >= _len - 1:
                return True
        return _max >= _len - 1

本文参考自:
https://github.com/grandyang/leetcode/ &
https://github.com/azl397985856/leetcode


标题: daily leetcode - jump-game - !
文章作者: lonuslan
文章链接: https://louislan.com/articles/2020/02/07/1581052629528.html
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Hi I'm LouisLan
    评论
    0 评论
avatar

取消