1. 程式人生 > >[LeetCode] Jump Game II

[LeetCode] Jump Game II

nac eps 心算 ini 空間復雜度 initial size 最小 rgb

Jump Game II

Given an array of non-negative integers, you are initially positioned at the first index of the array.

Each element in the array represents your maximum jump length at that position.

Your goal is to reach the last index in the minimum number of jumps.

For example:
Given array A = [2,3,1,1,4]

The minimum number of jumps to reach the last index is 2. (Jump 1 step from index 0 to 1, then 3 steps to the last index.)

解題思路:

最值問題,第一想到的就是動態規劃。用d[i]記錄從0到i最小的步數,則d[i]=min(d[k]+1),當中k是全部可以到達i的下標。最開始,我用一個vector數組記錄全部可以到達自身的下標,代碼例如以下:

class Solution {
public:
    int jump(vector<int>& nums) {
        int len = nums.size();
        if(len<2){
            return 0;
        }
        int d[len];
        d[0] = 0;
        vector<int> pre[len];
        for(int i=1; i<=nums[0] && i<len; i++){
            pre[i].push_back(0);
        }
        for(int i=1; i<len; i++){
            d[i] = INT_MAX;
            for(int j=0; j<pre[i].size(); j++){
                d[i] = min(d[i], d[pre[i][j]] + 1);
            }
            for(int j=i+1; j<=(nums[i] + i) && j<len; j++){
                pre[j].push_back(i);
            }
        }
        return d[len-1];
    }
};
時間復雜度為O(n*n),空間復雜度為O(n*n)。超時錯誤。

後經過改進。不須要記錄前驅節點,代碼例如以下,空間復雜度變為O(n)。但時間復雜度仍為O(n*n),產生超時錯誤。

class Solution {
public:
    int jump(vector<int>& nums) {
        int len = nums.size();
        if(len<2){
            return 0;
        }
        int d[len];
        for(int i=1; i<len; i++){
            d[i] = INT_MAX;
        }
        d[0] = 0;
        for(int i=0; i<len; i++){
            for(int j=i+1; j<=(nums[i]+i) && j<len; j++){
                d[j]=min(d[j], d[i] + 1);
            }
        }
        return d[len-1];
    }
};
水中的<。)#)))≦給我們一個非常好的解法:http://fisherlei.blogspot.com/2012/12/leetcode-jump-ii.html,採用貪心算法,記錄第k步最多可以走,且對第k+1步有影響的範圍[Left, Right],每走一步,left變成right+1。right變成[left, right]區間內走一步最遠的下標。這裏與上述方法的根本差別就是left=right+1,而非left=left+1,這樣可以降低非常多計算。

由於[left+1, right]已經在[left, right]時已經計算過了。

class Solution {
public:
    int jump(vector<int>& nums) {
        int len = nums.size();
        int left = 0;
        int right = 0;
        int count = 0;
        while(right<len-1){
            count++;
            int mostRight = right;
            for(int i=left; i<=right; i++){
                mostRight = max(mostRight, i+nums[i]);
                if(mostRight>=len - 1){
                    break;
                }
            }
            left = right + 1;
            right=mostRight;
            if(right<left){
                return -1;
            }
        }
        
        return count;
    }
};


[LeetCode] Jump Game II