【前端面试常见算法题系列】45. 跳跃游戏 II(中等)

205 阅读2分钟

“Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。”

一、题目描述

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

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

你的目标是使用最少的跳跃次数到达数组的最后一个位置。

假设你总是可以到达数组的最后一个位置。

示例 1:

输入: nums = [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。
     从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。

示例 2:

输入: nums = [2,3,0,1,4]
输出: 2

提示:

  • 1 <= nums.length <= 104
  • 0 <= nums[i] <= 1000

二、思路分析

这道题是 55. 跳跃游戏(中等) 的进阶。题目明确告诉我们:一定能够跳到数组的最后一个元素,要我们以尽可能少的次数跳到最后一个元素。

我们以 nums = [2,3,1,1,4] 来模拟一下跳跃过程:
遍历 nums 数组,首先走到 2 ,此时可以跳跃 2 步的距离,此时发现后面两步中,最远可以跳 3 步,因此选择先跳 1 步到 3 的位置,然后再跳 3 步直接到数组的最后一个元素。

然而这只是我们人为的判断,计算机在未遍历到后面的元素时是不知道可以跳多远的,更不可能选择最佳的跳跃方案。 但是结合模拟过程,我们思考出如下方案:

  • 首先,定义 end 表示跳跃到的位置,distance 表示最远的跳跃距离(以数组第一个元素为起点),count 表示跳跃的次数。
  • 然后,遍历 nums 数组,更新 distance 为最远的跳跃距离,(根据当前元素的值跳跃,值为几就跳几步,但并不是真的跳,而是在大脑中模拟这个过程),判断 end == i (表示遍历到跳跃的位置了)是否为真,不是的话就继续遍历,是的话就说明还未到达最后一个元素,还要接着跳,因此 count++ ,并且跳 distance 步(要跳当然就跳最远的距离,即更新 end = distance ,同样不是真的跳,而是在大脑中模拟这个过程)。

如果遍历到最后依然 end != distance ,说明已经跳的足够远了,距离超出了数组的长度,也就无需 count++ 了。

三、AC 代码

class Solution {
public:
    int jump(vector<int>& nums) {
        int end = 0, distance = 0;
        int count = 0;
        for (int i = 0; i < nums.size() - 1; i++) {
            distance = max(distance, nums[i] + i);
            if (end == i) {
                count++;
                end = distance;
            }
        }
        return count;
    }
};