算法——Week17

45. 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.

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.


解题思路
我最开始是把它看成了一个有向图,要找出从源点到终点的最短路径,考虑了Dijkstra算法。因为这个图从源点开始是依次展开的,所以从头开始遍历就可以,不需要单独取出可到达的点。但是当节点很多的时候,会超时。代码如下:

class Solution {
public:
    int jump(vector<int>& nums) {
        int n = nums.size();
        vector<int> dist(n, -1);
        dist[0] = 0;
        for(int i = 0; i < n - 1; i++) {
            for(int j = i + 1; j < nums[i] + i + 1 && j < n; j++) {
                if(dist[j] == -1) {
                    dist[j] = dist[i] + 1;
                    continue;
                }
                if(dist[j] != -1) {
                    dist[j] = dist[i] + 1 > dist[j] ? dist[j] : dist[i] + 1;
                }
            }
        }
        return dist[n-1];
    }
};

看了别人的解法,这道题应该是用宽度优先搜索实现会更好。以题中的例子:
第一层遍历:2
第二层遍历:3 1
第三层遍历:1 4
那么结果就应该是3-1=2。
遍历vector时,不需要依次遍历,而是要根据nums[]选择出最大遍历值,改变遍历的起始点和终点,知道可以到达目的节点。
代码如下:

class Solution {
public:
    int jump(vector<int>& nums) {
        int n = nums.size();
        int step = 0; //遍历次数
        int start = 0; //每次遍历的起点
        int end = 0; //每次遍历的终点
        while(end < n - 1) {
            step++;
            int nextend = end + 1;
            for(int i = start; i <= end; i++) {
                //如果正在遍历的点可以直接跳到目的节点
                if(i + nums[i] >= n - 1) {
                    return step;
                }
                nextend = max(nextend, i + nums[i]);
            }
            start = end + 1;
            end = nextend;
        }
        return step;
        
    }
};

猜你喜欢

转载自blog.csdn.net/melwx/article/details/85373266