【LeetCode 45 Jump Game II】

Description:

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.

Example:

Input: [2,3,1,1,4]
Output: 2
Explanation: 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.

Note:

You can assume that you can always reach the last index.

Solution1:(BFS思路)


  1. 初始:点集中只包含index为0的起点(id:0)
  2. 更新:循环更新该点集,每更新一次,即将jumpCount的计数器加1(点集中的点以下标唯一标识,并可以按照下标大小顺序表示,因此点集的范围可由left, right 两个值确定左右边界,闭区间中的所有下标代表的点即构成了当前点集)
  3. 说明:点集中的点均是从上一次点集中的某个点一步可达的点(已经存在于上一次点集中的点无需考虑,因为该点属于上一层)
  4. 终止:更新的终止条件为当前点集的右边界right已经大于等于len-1,即数组最后一个点,此时,所有节点均遍历完毕,每个节点都归属到了相应的层。

举例:

    在[2, 3, 1, 1, 4]中,初始点集为id:0的点,值为2,对应树的第0层, left=0,right=0【jumpCount=0】;第一次更新点集,因为id:1(值为3)和id:2(值为1)均可从id:0的点一步可达,因此更新点集,即当前点集为id:1和id:2,对应树的第1层【jumpCount++】;第二次更新点集,因为从id:1一步可达的并还未被归属到某一层的点有id:3,id:4,从id:2一步可达的点有id:3,因此更新点集,即id:3 id:4,对应树的第2层【jumCount++】,因为此时点集中已经有id:len-1的点了,因此停止更新,返回jumpCount

补充说明:

  • 如何更新点集? 【顺序遍历当前点集中的每一个点,不断更新maxRight,即从当前点集中的点最远的能一步可达的点的id(即下标)是多少; 遍历更新完毕后,先重置left,令left=right+1,再重置right,令right=maxRight】
  • 更新点集的过程即是如何通过当前层的节点构造下一层的节点

图解:

             

Code:

findMinJump(int arr[], int len){
    int left=0, right=0, maxRight=0, jumpCount=0;
    while(right < len-1){
        int i;
        for(i=left; i<=right; i++){
            maxRight = max(maxRight, i+arr[i]);
        }
        left = right + 1;
        right = maxRight;
        jumpCount++;
    }
    return jumpCount;
}

如想进一步打印最短的跳跃路径:

findMinJump2(int arr[], int len){
    int left=0, right=0, maxRight=0, jumpCount=0, keyPoint;
    while(right < len-1){
        keyPoint = left;
        int i;
        for(i=left; i<=right; i++){
            if(i+arr[i] > maxRight){
                maxRight = i+arr[i];
                keyPoint = i;
            }
        }
        cout << keyPoint << endl; //print inner keyPoint
        left = right + 1;
        right = maxRight;
        jumpCount++;
    }
    cout << len-1 << endl;//print last keyPoint(len-1)
    return jumpCount;
}

Solution2:DP


Code:

int findMinJump3(int arr[], int len){
    int MAX_LEN = 30000;
    int dp[MAX_LEN];
    for(int i=0; i<len; i++)
        dp[i] = len;
    dp[0] = 0;
    for(int i=1; i<len; i++){
        for(int j=0; j<i; j++){
            if(arr[j]+j >= i){
                if(dp[j]+1 < dp[i]){
                    dp[i] = dp[j] + 1;
                    break;//一定要有break,因为dp值是非严格单调递增,找到一个比当前dp[i]小
                    //的j,就没有必要继续向后搜索,即dp[j1]+1 <= dp[j2]+1 (j1<j2)
                }
            }
        }
    }
    return dp[len-1];
}

猜你喜欢

转载自blog.csdn.net/lqy0927/article/details/81504047