leetcode-LCP 09. 最小跳跃次数

 题目是LeetCode2020春季全国编程大赛个人赛的第四题,链接:LCP 09. 最小跳跃次数。具体描述见原题。

 这道题是hard难度的,先讲一种当时竞赛时想到的做法,就是用一个arrived数组记录在第count步所能到达的位置遍历数组的过程中,发现当前位置i可以跳出终点,则将arrived[i]置为true,如果当前位置已经是arrived[i]==true了,则此后所有位置都可以置为true了(因为后面这些位置都可以跳回到当前位置)。时间复杂度为 O ( n 2 ) O(n^{2}) O(n2),空间复杂度为 O ( n ) O(n) O(n)

 JAVA版代码如下:

class Solution {
    public int minJump(int[] jump) {
        // arrived[i]:从编号i开始可以通过count次越过N-1
        boolean[] arrived = new boolean[jump.length];
        int count = 0;
        int mostLeft = jump.length - 1;
        while (true) {
            for (int i = 0; i < jump.length; ++i) {
                if (arrived[i]) {
                    ++i;
                    while (i <= mostLeft) {
                        arrived[i++] = true;
                    }
                    break;
                }
                if (i + jump[i] >= jump.length || arrived[i + jump[i]]) {
                    arrived[i] = true;
                }
            }
            while (mostLeft >= 0 && arrived[mostLeft]) {
                --mostLeft;
            }
            ++count;
            if (arrived[0]) {
                break;
            }
        }
        return count;
    }
}

 提交结果如下:


 然后又可以用动态规划的方法,假设dp[i]表示从第i位跳出N-1所需要的最小次数,则从右往左遍历,如果有i+jump[i]>=N,则说明可以一步跳出,所以dp[i]=1,否则需要跳到i+jump[i],所以此时dp[i]=dp[i+jump[i]]+1。另外得到一个dp[i]之后,还需要考虑其后面的位置有可能通过跳回i再跳出N-1,所以需要遍历后面所有j直到dp[j],因此在这个j后面的都可以通过跳回j再跳出N-1,最多需要的次数也只是dp[j]+1<=dp[i]+1,保证不比跳回i需要的次数更多。

 JAVA版代码如下:

class Solution {
    public int minJump(int[] jump) {
        // dp[i]:从i跳出N-1需要的最少次数\
        int N = jump.length;
        int[] dp = new int[N];
        for (int i = N - 1; i >= 0; --i) {
            if (i + jump[i] >= N) {
                dp[i] = 1;
            }
            else {
                dp[i] = dp[i + jump[i]] + 1;
            }
            for (int j = i + 1; j < N && dp[j] >= dp[i] + 1; ++j) {
                // j位置上的可以先跳回到i再通过i跳出N-1,遍历到dp[j] < dp[i] + 1为止
                // 因为在这个j之后的dp都可以通过跳到j再跳出N-1,次数(dp[j] + 1 < dp[i] + 1)不会比跳回i更多
                dp[j] = dp[i] + 1;
            }
        }
        return dp[0];
    }
}

 提交结果如下:


 Python版代码如下:

class Solution:
    def minJump(self, jump: List[int]) -> int:
        N = len(jump)
        dp = [0] * N
        for i in range(N - 1, -1, -1):
            if i + jump[i] >= N:
                dp[i] = 1
            else:
                dp[i] = dp[i + jump[i]] + 1
            j = i + 1
            while j < N and dp[j] >= dp[i] + 1:
                dp[j] = dp[i] + 1
                j += 1
        return dp[0]

 提交结果如下:


你可能感兴趣的:(LeetCode,java,leetcode,动态规划,算法,python)