LeetCode面试150——45跳跃游戏II

题目难度:中等

默认优化目标:最小化平均时间复杂度。

Python默认为Python3。

目录

1 题目描述

2 题目解析

3 算法原理及代码实现

3.1 反向查找

3.2 正向查找

参考文献


1 题目描述

给定一个长度为 n0 索引整数数组 nums。初始位置为 nums[0]

每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i + j] 处:

  • 0 <= j <= nums[i]

  • i + j < n

返回到达 nums[n - 1] 的最小跳跃次数。生成的测试用例可以到达 nums[n - 1]

示例 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

  • 题目保证可以到达 nums[n-1]

2 题目解析

LeetCode面试150——55跳跃游戏不同的点在于,输出变成了最小的从0位置跳跃到数组最后的位置所需要的步数。输入没变,还是数组nums。约束条件为,跳转步数最大为当前位置的元素的值,即nums[i],i表示当前位置。

题目中0索引的意思无非是禁用哈希表。枚举肯定能做出来,也就是暴力求解,不考虑。平均时间复杂度为


O(\frac{1}{n}\sum_{i=1}^ni!)=O(n!)
 

3 算法原理及代码实现

以下两种方法都是用贪心思想,但实现的策略不同。

3.1 反向查找

最终输出的是到达nums最后位置所需最少的跳跃步数,也就是说,无论跳跃的过程是如何的,最终都要到达nums最后的位置。因此,我们可以反过来,找到最后一步跳跃前的位置,依此类推往前查找。数学公式如下


pos[last]=pos[last-1]+[0,nums[pos[last-1]]]
 

数组pos用于记录跳跃的轨迹,[0,nums[pos[last]]]表示可跳跃的步数范围。

我们目标是要找最小的步数。如果只有唯一的last-1last位置,无其他可选。要是有两条以上的可选路径,我们贪心的选择下标最小的那个。也就是选min (last-1)。

又因为当前状态只与前一个状态有光,因此可以使用一个变量position来代替状态数组pos

平均时间复杂度为O(n^2),平均空间复杂度为O(1)。

C++程序实现

class Solution {
public:
    int jump(vector<int>& nums) {
        int position = nums.size() - 1;
        int steps = 0;
        while (position > 0) {
            for (int i = 0; i < position; i++) {
                if (i + nums[i] >= position) {
                    position = i;
                    steps++;
                    break;
                }
            }
        }
        return steps;
    }
};

Python代码实现

class Solution:
    def jump(self, nums: List[int]) -> int:
        position = len(nums) - 1
        steps = 0
        while position > 0:
            for i in range(position):
                if i + nums[i] >= position:
                    position = i
                    steps += 1
                    break
        return steps

3.2 正向查找

改为正向查找,从0位置往后,每次贪心地找当前位置能到达的最远位置。如果数组的i位置的最大跳跃距离nums[i]+i大于当前跳跃起始点所在位置pos,用nums[i]+i更新pos,反之不更新,即:


pos=max(pos,nums[i]+i)
 

平均时间复杂度为O(n),平均空间复杂度为O(1)。

C++代码实现

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

Python代码实现

class Solution:
    def jump(self, nums: List[int]) -> int:
        pos, n, end, step = 0, len(nums), 0, 0
        for i in range(n - 1):
            if pos >= i:
                pos = max(pos, i + nums[i])
                if i == end:
                    end = pos
                    step += 1
        return step

参考文献

力扣面试经典150题

力扣官方题解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值