Leetcode题解系列——45. Jump Game II(c++版)

版权声明: https://blog.csdn.net/dickdick111/article/details/83280612

题目链接:45. Jump Game II

题目大意:与之前的跳跃游戏一样,从下标0出发,查看是否能跳跃到数组的最后一个下标。数组的每个元素都是能跳跃的距离,现在要求输出跳跃到最后下标的最小步数。

注意点:

  1. 这次要求所给的数组都能到达最后下标,即无需考虑到达不了的情况
  2. 不一定每次都走最大的距离,才能最快到达最后下标,故要改变之前的贪心策略
  3. 注意判断数组只有一个元素的情况

一.算法设计

这次要在第一个跳跃游戏的基础下,添加一个count数组,储存每个结点到达下标所用的最小跳跃次数,但是要记得将第一个下标的跳跃次数设置为0,即不需要跳跃即可到达。

每个结点找出所能到达的最远距离,如果这个最远距离小于n-1即最后下标,那么将count数组对应下标的元素赋值,该值为count[i]+1即到达该i结点的次数+1和它本身的次数的最小值
count[max_num] = min(count[i]+1, count[max_num]);

当最远距离大于最大下标,也亦然,只不过不是赋值最远距离下标而是赋值n-1.

最后count[n-1]所储存的一定是到达该下标的最少次数,这可以通过将问题分解成许多子问题来思考,因为子问题也是找到达前一个点的最少步数,所以最少步数的和也一定是到达终点的最少步数。

二.算法实现

class Solution {
public:
    int jump(vector<int>& nums) {
        int n = nums.size();
        if(n == 1) return 0;
        int max_num = 0;
        int count[30000]={0}; //要让count[0] = 0
        for(int j = 1; j < 30000; j++){
            count[j] = 300000;
        }
        for(int i = 0; i < n; i++){ 
            max_num = max(max_num, i+nums[i]);
            if(max_num <= n-1) count[max_num] = min(count[i]+1, count[max_num]);
            else count[n-1] = min(count[i]+1,count[n-1]);
        }
        return count[n-1];
    }
};

三.算法改进

当然也可以不用维持这一个count数组,只需要每一次所要跳跃的选择都选择能跳跃最远的结点。怎么为能跳跃最远呢,不仅要当前的下标大,还与数组元素相关
next_max=max(next_max,nums[i]+i);

这样选择多次,直到判断最远距离大于最远下标,即可输出选择的次数。

class Solution {
public:
    int jump(vector<int>& nums) {
        if(nums.size()<2){
            return 0;
        }
        int level=0,current_max=0,next_max=0,i=0; 
        while(i<nums.size()){
            level++; 
            for(;i<=current_max;i++){
                next_max=max(next_max,nums[i]+i);
                if(next_max>=nums.size()-1) return level; 
            }
            current_max=next_max;
        }
        return level;
    }
};

猜你喜欢

转载自blog.csdn.net/dickdick111/article/details/83280612
今日推荐