LeetCode 45.跳跃游戏II

题目

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

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

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

题目链接

示例

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

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

题目分析

逆向查找

题目给出的说明是总是可以到达最后一个位置,所以直观想到的第一种方法就是逆向贪心查找,从最后一位向前查找,找到可以到达最后一个元素的最远的元素,依此循环。

这种算法的时间复杂度是$ O(n^2) $,在c语言里能通过,使用c++会超时,所以需要找到时间复杂度更低的算法。

正向查找

逆向查找虽然直观,但是复杂度高,我们依然借助贪心算法的思路,正向查找,也可以找到结果。

以2、3、1这数组为例,从第一个元素最多可以跳两步,如果我们每次都选择两步之内的最大值(能到达最远距离的元素),那就可以用最小的步数到达最后一个元素。

首先要写出寻找步长内最大值的函数:

int findmax(vector<int> nums, int left, int right){
    int res = left;
    for (int i = left; i < right; i++){
        if (nums[i] + i >= res + nums[res]) res = i;
    }
    return res;
}

然后是遍历的过程:

int res = 0;
int pos = 0;
while (true){
    if (pos + nums[pos] >= nums.size() - 1){
        res++;
        break;
    }else {
        pos = findmax(nums, pos, pos + nums[pos]);
        res++;
    }
}

完整的过程见最后一部分。


题目解答

逆向查找

int jump(int* nums, int numsSize){
    int pos = numsSize - 1;
    int res = 0;
    while (pos > 0){
        for (int i = 0; i < pos; i++){
            if (i + nums[i] >= pos){
                res++;
                pos = i;
            }
        }
    }
    return res;
}

正向查找

class Solution {
public:
    int findmax(vector<int>& nums, int left, int right){
        int temp = left;
        for (int i = left; i <= right; i++){
            if (nums[i] + i >= nums[temp] + temp) temp = i;
        }
        return temp;
    }
    int jump(vector<int>& nums) {
        int len = nums.size();
        if (len == 1) return 0;
        int res = 0;
        int pos = 0;
        while (true){
            if (pos + nums[pos] >= len - 1){
                res++;
                break;
            }else {
                pos = findmax(nums, pos, pos + nums[pos]);
                res++;
            }
        }
        return res;
    }
};
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。