您的位置:首页 > 其它

LeetCode Jump Game

2015-06-28 12:19 260 查看
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.

Determine if you are able to reach the last index.
Solution:

Firstly, we may easily want to solve this problem with BFS or DFS. But using a system stack will cause stack overflow, and BFS may be easier to code.

A list like LinkedList can be used as queue, which stores all the tokens that are to be operated.

For each token in queue:

if it has been operated, vis[i] = true, then skip it.

else if this token+nums[token] is equal or greater than the last index of array, then return true.

else for each index within the range [ token+1, token+nums[token] ), add them into the queue.

until the queue is empty.

However we get a TLE with BFS, so another method is required.

Let us explore this array again. All the integers are non-negative, so for all the number that is greater than zero, it can continue to 'go on' to its next number. From this point, we may find the new method: find whether there
is a gap in the nums[] array, if so then return false, else return true.

How to find a gap:

we can tell from the examples the feature of such 'false' array: 4 3 2 1 0.

--- every time we find a zero, we can scan the index from token to zero; for each index i, if i+nums[i] > tot then continue the big loop, if no 'continue loop;' here, that is to say we can go to the end of the inner loop, then
it means there exits a gap marked by zero in the array, so return false.

Pay attention that although there are two for loop, actually it is equal to one for loop. The time complexity is still O(n).

import java.util.*;

public class Solution {
boolean vis[];

public boolean canJump(int[] nums) {
if (isBlockedZero(nums))
return false;
return true;
// vis = new boolean[nums.length];
// return bfs(nums, 0);
}

boolean isBlockedZero(int nums[]) {
loop: for (int i = 0; i < nums.length - 1; i++) {
if (nums[i] == 0) {
for (int j = i - 1; j >= 0; j--) {
if (j + nums[j] > i)
continue loop;
}
return true;
}
}
return false;
}

boolean bfs(int[] nums, int tot) {
LinkedList<Integer> queue = new LinkedList<Integer>();

queue.add(0);

int u, r;
while (!queue.isEmpty()) {
u = queue.poll();
// System.out.println(u);
if (u + nums[u] >= nums.length - 1)
return true;
if (vis[u])
continue;
vis[u] = true;
r = Math.min(nums.length - 1, u + nums[u]);
for (int i = u + 1; i <= r; i++) {
if (vis[i])
continue;
queue.add(i);
}
}
return false;
}
}


最后再多说一下, 因为网上看了很多题解,有部分是错误的。另一种可行的方法是一维动态规划+线性扫描。这个做法是在遍历的同时维护一个max值,记录能够达到的最远距离。同样是看这个max值在遇到0值的时候能否越过这个0,也就是我这个方法所说的‘gap’。

两个方法,一种是线性扫描,在线,复杂度为O(n);另外一种是如上代码一样,以0为分割点,其实可以离线做,现在这样在线处理理论上复杂度不变,复杂度也是O(n)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: