17

Jump Game: Given an array, start from the first element and reach the last by jumping. The jump length can be at most the value at the current position in the array. The optimum result is when you reach the goal in minimum number of jumps.

What is an algorithm for finding the optimum result?

An example: given array A = {2,3,1,1,4} the possible ways to reach the end (index list) are

  1. 0,2,3,4 (jump 2 to index 2, then jump 1 to index 3 then 1 to index 4)
  2. 0,1,4 (jump 1 to index 1, then jump 3 to index 4)

Since second solution has only 2 jumps it is the optimum result.

Alwaysblue
  • 9,948
  • 38
  • 121
  • 210
user973931
  • 515
  • 1
  • 4
  • 13
  • possible duplicate of [Fastest algorithm to hop through an array](http://stackoverflow.com/questions/7353813/fastest-algorithm-to-hop-through-an-array) – PengOne Jan 31 '12 at 01:42
  • Does this answer your question? [Fastest algorithm to hop through an array](https://stackoverflow.com/questions/7353813/fastest-algorithm-to-hop-through-an-array) – ggorlen Jan 22 '21 at 02:11

6 Answers6

17

Overview

Given your array a and the index of your current position i, repeat the following until you reach the last element.

Consider all candidate "jump-to elements" in a[i+1] to a[a[i] + i]. For each such element at index e, calculate v = a[e] + e. If one of the elements is the last element, jump to the last element. Otherwise, jump to the element with the maximal v.

More simply put, of the elements within reach, look for the one that will get you furthest on the next jump. We know this selection, x, is the right one because compared to every other element y you can jump to, the elements reachable from y are a subset of the elements reachable from x (except for elements from a backward jump, which are obviously bad choices).

This algorithm runs in O(n) because each element need be considered only once (elements that would be considered a second time can be skipped).

Example

Consider the array of values a, indicies, i, and sums of index and value v.

i ->  0   1   2   3   4   5   6   7   8   9  10  11  12
a -> [4, 11,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1]
v ->  4  12   3   4   5   6   7   8   9  10  11  12  13

Start at index 0 and consider the next 4 elements. Find the one with maximal v. That element is at index 1, so jump to 1. Now consider the next 11 elements. The goal is within reach, so jump to the goal.

Demo

See here or here with code.

cheeken
  • 33,663
  • 4
  • 35
  • 42
  • How does it work for this case: 4,11,1,1,1,1,1,1,1,1,1,1,1 ? – ElKamina Jan 28 '12 at 01:15
  • @ElKamina I amended my answer with your question. – cheeken Jan 28 '12 at 01:25
  • 1
    What if it was 3, 5, 1, 4, 1, 1, 1, 1? – Shahbaz Jan 28 '12 at 01:36
  • @Shahbaz, start at 0:3. Jump to the element with maximal v in 1:5, 2:1, 3:4, for which 3:4 has the maximum. At 3:4, the goal is in reach, so jump to the goal. – cheeken Jan 28 '12 at 01:55
  • 1
    This cannot be optimal. You **branch too early**, with no guarantee that there isn't a large cost in this path later on. Try again with this example: 2,6,1,15,1,1,1,1,1,1,1,1,1,1,1,1. Note that 6+1 is larger than 1+2. Only a systematic search of **all paths** can guarantee the solution, and dynamic programming merely caches repeating results to do it faster. – vgru Jan 28 '12 at 09:01
  • @Groo Indeed, 6+1 is larger. Making the moves: 0:2 => 1:6 => 3:15 => end. That appears the optimal solution, no? – cheeken Jan 28 '12 at 12:47
  • @Groo I have added a demo. I can't seem to fault this method. Do you have another counterexample (or did I misinterpret the one you provided earlier)? – cheeken Jan 28 '12 at 14:43
  • No, you are right. It's best to get the largest coverage each time. I didn't think this through and assumed that it's a DP problem. +1, good work! – vgru Jan 28 '12 at 15:28
  • @cheeken, greedy solutions are always very tricky. I also however can't seem to figure out a counter example. Perhaps one that involves many steps might do. Usually, a greedy solution involves a mathematical proof, which you might want to present. – Shahbaz Jan 28 '12 at 15:28
6

Dynamic programming.

Imagine you have an array B where B[i] shows the minimum number of step needed to reach index i in your array A. Your answer of course is in B[n], given A has n elements and indices start from 1. Assume C[i]=j means the you jumped from index j to index i (this is to recover the path taken later)

So, the algorithm is the following:

set B[i] to infinity for all i
B[1] = 0;                    <-- zero steps to reach B[1]
for i = 1 to n-1             <-- Each step updates possible jumps from A[i]
    for j = 1 to A[i]        <-- Possible jump sizes are 1, 2, ..., A[i]
        if i+j > n           <-- Array boundary check
            break
        if B[i+j] > B[i]+1   <-- If this path to B[i+j] was shorter than previous
            B[i+j] = B[i]+1  <-- Keep the shortest path value
            C[i+j] = i       <-- Keep the path itself

The number of jumps needed is B[n]. The path that needs to be taken is:

1 -> C[1] -> C[C[1]] -> C[C[C[1]]] -> ... -> n

Which can be restored by a simple loop.

The algorithm is of O(min(k,n)*n) time complexity and O(n) space complexity. n is the number of elements in A and k is the maximum value inside the array.

Note

I am keeping this answer, but cheeken's greedy algorithm is correct and more efficient.

Shahbaz
  • 46,337
  • 19
  • 116
  • 182
  • You seem to have thought this through very thoroughly, but it is more complex than the solution I provided. Do you see a flaw in my solution? Edit: Oops, I just noticed you are the one who responded to my answer, not ElKamina. – cheeken Jan 28 '12 at 01:44
  • It's actually a very simple dynamic programming solution. It doesn't even go 2D. On the other hand I have done a lot of algorithm design. – Shahbaz Jan 28 '12 at 15:27
  • @Shahbaz: it is a simple DP solution, but in time and space complexity it is inferior to cheeken's solution. I know it's **safer** to go for a known algorithm (when I saw the question, DP was also the first thing that came to my mind), but O(n)/O(1) complexity is really hard to beat. And I find it unlikely than a counterexample with "many steps" would achieve something which cannot be demonstrated in 20 steps. – vgru Jan 28 '12 at 17:06
  • @kalyanaramansanthanam, regarding your edit: `if B[i+j] > B[i]+1` doesn't need to have `>=` because if the new path is equally good as the old path, there is no point in updating it. You wouldn't gain any better path, but just _another_ equally good path. In fact, with `>=` it would still be ok, but it would produce different paths with the same minimum number of jumps as the algorithm above. – Shahbaz Nov 18 '13 at 15:50
  • @Shahbaz Just like you have the array B[n], what if we have an array say C[n] where, C[i] = minimum number of jumps required to reach A[n] from 'i'. We could start from the end such that C[n] = 0 and our answer will be in C[1]. At each step, if distance b/w 'n' and the position 'i' can be covered in A[i] then C[i] = 1 otherwise C[i] = C[i + A[i]] + 1. This solution is linear in terms of running time and space covered. – user1071840 Jun 18 '14 at 23:13
  • @user1071840, I didn't think thoroughly about your solution, but if I understood it correctly, it's also greedy based on the same property as in Cheeken's answer. – Shahbaz Jun 19 '14 at 11:06
4

Construct a directed graph from the array. eg: i->j if |i-j|<=x[i] (Basically, if you can move from i to j in one hop have i->j as an edge in the graph). Now, find the shortest path from first node to last.

FWIW, you can use Dijkstra's algorithm so find shortest route. Complexity is O( | E | + | V | log | V | ). Since | E | < n^2, this becomes O(n^2).

ElKamina
  • 7,747
  • 28
  • 43
1

We can calculate far index to jump maximum and in between if the any index value is larger than the far, we will update the far index value.

Simple O(n) time complexity solution

public boolean canJump(int[] nums) {
    int far = 0;
    for(int i = 0; i<nums.length; i++){
        if(i <= far){
            far = Math.max(far, i+nums[i]);
        }
        else{
            return false;
        }
    }
    return true;
}
Community
  • 1
  • 1
0

start from left(end)..and traverse till number is same as index, use the maximum of such numbers. example if list is

   list:  2738|4|6927
   index: 0123|4|5678

once youve got this repeat above step from this number till u reach extreme right.

273846927
000001234

in case you dont find nething matching the index, use the digit with the farthest index and value greater than index. in this case 7.( because pretty soon index will be greater than the number, you can probably just count for 9 indices)

Kshitij Banerjee
  • 1,678
  • 1
  • 19
  • 35
0

basic idea:

start building the path from the end to the start by finding all array elements from which it is possible to make the last jump to the target element (all i such that A[i] >= target - i).

treat each such i as the new target and find a path to it (recursively).

choose the minimal length path found, append the target, return.

simple example in python:

ls1 = [2,3,1,1,4]
ls2 = [4,11,1,1,1,1,1,1,1,1,1,1,1]

# finds the shortest path in ls to the target index tgti
def find_path(ls,tgti):

    # if the target is the first element in the array, return it's index.
    if tgti<= 0:
        return [0]

    # for each 0 <= i < tgti, if it it possible to reach
    # tgti from i (ls[i] <= >= tgti-i) then find the path to i

    sub_paths = [find_path(ls,i) for i in range(tgti-1,-1,-1) if ls[i] >= tgti-i]

    # find the minimum length path in sub_paths

    min_res = sub_paths[0]
    for p in sub_paths:
        if len(p) < len(min_res):
            min_res = p

    # add current target to the chosen path
    min_res.append(tgti)
    return min_res

print  find_path(ls1,len(ls1)-1)
print  find_path(ls2,len(ls2)-1)

>>>[0, 1, 4]
>>>[0, 1, 12]
yurib
  • 8,043
  • 3
  • 30
  • 55
  • For this kind of questions, pseudocode with well named variables is more useful than actual code with badly named ones (IMHO). Could you describe the algorithm in words? – vgru Jan 28 '12 at 09:10
  • you're right, i've updated my answer with an explanation and some comments – yurib Jan 28 '12 at 12:40