LeetCode Jump Game && Jump GameII

LeetCode Jump Game && Jump GameII

又是每日LeetCode Time, 这里直接解决Jump Game和Jump GameII;

先上题目:

Jump Game

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.

Determine if you are able to reach the last index.

For example:

A = [2,3,1,1,4], return true.

A = [3,2,1,0,4], return false.

题意: 给出一个非负整数序列, 初始位置在数组下标0处, 每个元素代表能够跳跃的最远距离; 判断一个跳跃数组能否跳到数组末端, 下标n-1处;

Jump GameII

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

题意: 给出一个非负整数序列, 初始位置在数组下标0处, 每个元素代表能够跳跃的最远距离; 求跳跃数组跳到数组末端, 下标n-1处所需的最少步数;


分析:

显然, 题目是一个图的最短路问题, 不难发现, 每个下标即为图中顶点, 而跳跃距离则隐含着顶点v所能够到达的顶点集合; 当然这也是后来经过系统地学习数据结构和算法分析后才领悟到的; 对于JumpGame2, 由于每次跳跃计数1次, 所以相当于无权图的最短路问题, 采用队列BFS就可以在O(n)时间复杂度内解决问题, 下面详细讨论;


-- 伊始:

(a)JumpGame1

不懂队列也不知道图, 所以这样做的, 先上代码:

<span style="font-size:14px;">class Solution {
public:
    bool canJump(int A[], int n) {
        int far = 0;
        for (int i = 0; i < n - 1 && far < n - 1; ++i){
        	if (i > far){
        		return false;
        	}
        	if (A[i] + i >= far){
        		far = A[i] + i;
        	}
        }
        if (far >= n - 1){
        	return true;
        }
        else return false;
    }
};</span>
分析:

-- 代码中far表示目前所能到达的最远处的下标; 

-- 我们从0出发, 向后扫描, 同时记录当前能到达的最远处far, 如果发现当前下标i比能到达的最远处far还远, 说明无法到达末位;

-- 优点是空间复杂度为O(1);


(b) JumpGame2

<span style="font-size:14px;"><span style="font-size:14px;">class Solution {
public:
    int jump(int A[], int n) {
        int distance[n], ct = 1;//ct start 1, important!
        for (int i = 0; i < n; ++i){
            distance[i] = 0;
        }
        for (int i = 0; i < n && !distance[n-1]; ++i){
            if (i && !distance[i]){
                return -1;
            }
            while (ct <= i + A[i] && ct < n){
                distance[ct++] = distance[i] + 1;
            }
        }
        return distance[n-1];
    }
};</span></span>
分析:

-- 使用辅助数组distance记录当前的最小步数, 初始化为0;

-- ct代表所能到达的最远下标, 同上面的far;

-- 空间复杂度为O(n);


-- 进阶

(a)JumpGame1

使用队列BFS求解, 感觉更好理解, 图的可达性问题

<span style="font-size:14px;"><span style="font-size:14px;">class Solution {
public:
    bool canJump(int A[], int n) {
        if (n == 1)
            return true;
        queue<int> available;
        vector<int> visited(n, false);
        available.push(0); visited[0] = true;
        while (!available.empty()) {
            int cur = available.front(); available.pop();
            for (int i = A[cur]; i != 0; --i) {
                if (cur + i >= n - 1)
                    return true;
                if (visited[cur+i])
                    break;
                available.push(cur + i); visited[cur+i] = true;
            }
        }
        return false;
    }
};</span></span>
分析:

-- 时间复杂度O(n), 空间复杂度O(n)

-- 思路就是将所有可达点入队, 同时标记为visited, 直到队列为空

-- 此处循环从A[cur]开始, 这样可以稍微优化一些, 如判断已经可达, 就直接return true, 同时能够在visited[cur+i]为true时跳出循环


(b) JumpGame2

<span style="font-size:14px;"><span style="font-size:14px;">class Solution {
public:
    int jump(int A[], int n) {
        if (n == 1)
            return 0;
        queue<int> available, count;
        vector<int> visited(n, false);
        available.push(0); visited[0] = true;
        count.push(0);
        while (!available.empty()) {
            int cur = available.front(); available.pop();
            int cnt = count.front(); count.pop();
            for (int i = A[cur]; i != 0; --i) {
                if (cur + i >= n - 1)
                    return cnt + 1;
                if (visited[cur+i])
                    break;
                available.push(cur + i); count.push(cnt + 1);
                visited[cur+i] = true;
            }
        }
        return -1;
    }
};</span></span>
分析:

-- 此处除了使用available记录当前能够到达的点之外, 还需要用count来记录到达各个点时所需的跳跃步数;


最后:

无权图的最短路可由队列BFS求出, 当然对于不同的问题需要将其转化为已知的问题才可以, 又如已知hash表的元素, hash函数和处理冲突的方法, 求hash插入元素的顺序, 不难发现, 这实际上就是一个拓扑排序过程, 这便是问题的一个转化过程!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值