2020春季编程大赛 - 最小跳跃次数

LCP 09. 最小跳跃次数

来源: LeetCode LCP 09. 最小跳跃次数

题目描述

LCP 09. 最小跳跃次数
为了给刷题的同学一些奖励,力扣团队引入了一个弹簧游戏机。游戏机由 N 个特殊弹簧排成一排,编号为 0 到 N-1。初始有一个小球在编号 0 的弹簧处。若小球在编号为 i 的弹簧处,通过按动弹簧,可以选择把小球向右弹射 jump[i] 的距离,或者向左弹射到任意左侧弹簧的位置。也就是说,在编号为 i 弹簧处按动弹簧,小球可以弹向 0 到 i-1 中任意弹簧或者 i+jump[i] 的弹簧(若 i+jump[i]>=N ,则表示小球弹出了机器)。小球位于编号 0 处的弹簧时不能再向左弹。

为了获得奖励,你需要将小球弹出机器。请求出最少需要按动多少次弹簧,可以将小球从编号 0 弹簧弹出整个机器,即向右越过编号 N-1 的弹簧。

示例 1:

输入:jump = [2, 5, 1, 1, 1, 1]

输出:3

解释:小 Z 最少需要按动 3 次弹簧,小球依次到达的顺序为 0 -> 2 -> 1 -> 6,最终小球弹出了机器。

限制:

1 <= jump.length <= 10^6
1 <= jump[i] <= 10000

思路分析

- 定义数组dp[n]
- dp[i]代表从位置i处弹出机器所需要的最小跳数
- 位置i处的最小跳数取决于其后面的最小跳数+1 与 前面的最小跳数 + 1
从后向前遍历 dp[i] = i+jump[i] > n ? 1 : dp[i+jump[i]] + 1  // 当前能直接跳出去:往前跳一步的最小跳数+1
dp[j] >= dp[i] + 1 dp[j] = dp[i] + 1 // 从后往回跳一步 

代码

class Solution {
#define SIZE(A) ((int)A.size())
#define LENGTH(A) ((int)A.length())
#define MP(A,B) make_pair(A,B)
#define PB(X) push_back(X)
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,a) for(int i=0;i<(a);++i)
#define ALL(A) A.begin(),A.end()
using VI = vector<int>;
using VII = vector<VI>;
using VD = vector<double>;
typedef pair<int, int> PI;
public:
    int minJump(vector<int>& jump) {
        int n = SIZE(jump) - 1;
        int dp[SIZE(jump)];
        dp[n] = 1;
        for(int i = n-1; i>= 0; --i){
            dp[i] = i+jump[i]>n ? 1 : dp[i+jump[i]] + 1; // 能否直接跳出去,往前跳一步的最远步数+1 
            for(int j=i+1; j<SIZE(jump)&&dp[i]+1<dp[j]; ++j) dp[j] = dp[i] + 1; // 
        }
        return dp[0];
    }
};

算法分析

- 时间复杂度:O(n^2)
- 空间复杂度:O(1)

代码改进

看官方题解有O(n)解法但运行时间并不如上述的理想

你可能感兴趣的:(DP,LeetCode总结)