12

Problem: Minimum number of jumps to reach end

Given an array of integers where each element represents the max number of steps that can be made forward from that element. Write a function to return the minimum number of jumps to reach the end of the array (starting from the first element). If an element is 0, then we cannot move through that element.

Example:

Input: arr[] = {1, 3, 5, 8, 9, 2, 6, 7, 6, 8, 9} Output: 3 (1-> 3 -> 8 ->9) First element is 1, so can only go to 3. Second element is 3, so can make at most 3 steps i.e. to 5 or 8 or 9.

Source: http://www.geeksforgeeks.org/minimum-number-of-jumps-to-reach-end-of-a-given-array/

I have made a linear time algorithm for finding Minimum number of jumps required to reach end of an array.

The source code is as below:

int minJumpsUpdated(int arr[], int n)
{
  int *jumps = malloc(n * sizeof(int));  // jumps[n-1] will hold the result
  int i =1, j = 0;

  jumps[0] = 0;
  for (i = 1; i < n; ) { 

    // if i is out of range of arr[j], then increment j
    if (arr[j] + j < i && j < i) {

      j++;

    // else if i is within range of arr[j], 
    //   jumps for ith element would be jumps[j]+1
    } else if (arr[j] + j >= i && j < i) {

      jumps[i] = jumps[j] + 1;
      i++;

    } else {
      printf("solution does not exist");
      return -1;
    }
  }

  printf("jumps: ");
  for (i = 0; i < n; i++) {
    printf("%d, ", jumps[i]);
  }
  return jumps[n - 1];
}

Example:

1.) initially i=1, j=0 and arr[] = {1, 3, 6, 1, 0, 9};

jumps[] = 0,0,0,0,0,0

2.) as i is within range of arr[j] ie. i<= j+arr[j], number of jumps required to go to ith position would be min number of jumps till jth position + 1.

i=2, j=0, jumps[] = 0,1,0,0,0,0

3.) i>j+arr[j] i.e. j++;

i=2, j=1, jumps[] = 0,1,0,0,0,0

4.) i<=j+arr[j] i.e. jumps[i] = jumps[j]+1;

i=3, j=1, jumps[] = 0,1,2,0,0,0

5.) i<=j+arr[j] i.e. jumps[i] = jumps[j]+1;

i=4, j=1, jumps[] = 0,1,2,2,0,0

6.) i<=j+arr[j] i.e. jumps[i] = jumps[j]+1;

i=5, j=1, jumps[] = 0,1,2,2,2,0

7.) i>j+arr[j] i.e. j++;

i=5, j=2, jumps[] = 0,1,2,2,2,0

8.) i<=j+arr[j] i.e. jumps[i] = jumps[j]+1;

i=6, j=2, jumps[] = 0,1,2,2,2,3

------ END ------

I am not able to figure out under which test case this program will not work. I am asking this because on internet the optimized solution is using DP which is O(n^2). My solution is linear time. i.e. O(n). So I am assuming there are some cases which this algorithm will not handle. So I am curious what cases it does not handle.

Your help will be appreciated.

Thank you.

crisron
  • 363
  • 2
  • 5
  • 21
AlienOnEarth
  • 747
  • 7
  • 14
  • @Jarod42 I tried to improve a bit. – Grijesh Chauhan Apr 25 '14 at 19:32
  • 3
    Hm, we only have your program, and no description what it is supposed to do. If the program is just your problem description, then yes, it will always work, trivially. And since it is always linear, it can't describe the problem properly if somebody has proven a lower bound of `n²` for the original problem, obviously. So please give us a clear definition of the problem you are supposed to solve. Also: you might remove the C++ tag, this is C. Then, don't cast return of `malloc` and don't forget to `free` your array at the end. – Jens Gustedt Apr 25 '14 at 19:42
  • @JensGustedt: I have added problem statement. Also, I will make sure I free memory allocated. Thank you very much for pointing it out. – AlienOnEarth Apr 25 '14 at 19:48
  • @JensGustedt o(f) means an upper bound, not a lower bound. Also, why not just remind alien that it is common on SO to include the problem statement itself (instead of just a link to it) in the question? – G. Bach Apr 25 '14 at 20:45
  • Just generate random test cases and compare the results of the two algorithms to find a counter-example, if one exists. If you don't find one, that's not a proof that your algorithm is correct, but if you do, it's a proof that this is not the case, and only then it might be sensible to bring this to Stack Overflow in my opinion. By the way the DP approach can be implemented in O(n log n) via range-minimum queries. – Niklas B. Apr 25 '14 at 21:16
  • Also think about cases like `[4,1,1,4,1,1,1]`. The answer is 2 – Niklas B. Apr 25 '14 at 21:19
  • @G.Bach and @ JensGustedt: I have updated the question with description of the problem. Also I have included a link to source. – AlienOnEarth Apr 25 '14 at 21:24
  • @NiklasB. The code is giving numbers of jumps as 2 for input: {4,1,1,4,1,1,1}, which I think is a correct answer. – AlienOnEarth Apr 25 '14 at 21:25
  • @alien: Have you tested on random input? If not you should do that. If you are unable to find a counter-example, there is a chance that your algorithm is correct – Niklas B. Apr 25 '14 at 21:31
  • @NiklasB. : Thank you for your suggestions. I have already tested this code on many different random inputs. I also used all the inputs suggested in http://stackoverflow.com/questions/9041853/interview-puzzle-jump-game. Also I created some other test cases on my own and tried. It always gives correct result. That is why I posted this question to find out a case where this algorithm will fail. OR if there is any proof for correctness of the algorithm. – AlienOnEarth Apr 25 '14 at 21:38

3 Answers3

6

Summary of your algorithm:

  1. Take the first item and look how far you can get with this
    (incrementing i until arr[j]+j < i)
  2. Go to the next item that you can reach from the first one and that takes you at least to ith item.
  3. Repeat this until you reach the last entry.

First:
Yes it runs in O(n) since the algorithm pushes both i an j only one time from 1 to n in worst case.

Second
I have not seen a proof that O(n²) is the optimal time-complexity.

Thrid
You can visualize the arr like this ArrayJumpVisualization so this is exactly what your algorithm does. You can use this to proof by induction that your algorithm is correct. But as @Leo mentioned, there has to be a solution.

Fix for no-solution-case
Make sure that j < i holds.

AbcAeffchen
  • 14,400
  • 15
  • 47
  • 66
  • Cool visualization :) – Niklas B. Apr 25 '14 at 22:28
  • The visualization makes it look like the algorithm here is not O(n), and makes it look like O(N^2). Imagine input {9,8,7,6,5,4,3,2,1,0}. – Mooing Duck Feb 06 '15 at 00:14
  • The algorithm in the question contains two not nested loops that run in linear time. I realy don't see where the quadratic complexity should come from. The visualization does not show the complexity. – AbcAeffchen Feb 06 '15 at 00:47
1

I think your code is only correct if there is a solution, what if there is no solution for example what if the input is [0, 2 , 3 , 4] ?

Other than that I think your algorithm is correct, here is my solution when I solved this problem, it only need constant space, and still linear time. Basically for each step, you only jump to the position that could jump most steps in next step.

int jump(int A[], int n) {
    int jumps = 0;
    if(n < 2){
        return jumps;
    }
    int cur = 0; // current index,
    int cur_step;// number of step you can jump in current index 
    int last;    // last index
    int temp_max = cur; // temporary max jump distance 
    int temp_index = cur;// temporary index.

    while(cur < n){
        last = cur;
        cur_step = A[cur];
        if((cur + cur_step) >= n-1){ // if reached end of the array, return.
            jumps++;
            return jumps;
        }
        for(int ii = cur + 1; ii <= cur + cur_step; ii++){//go thru all the possible next position, and find the one that could jump most steps.
            if(A[ii] == 0){
                continue;
            }
            if(A[ii] + ii > temp_max){ // find the one that could jump most steps.
                temp_index = ii;
                temp_max = A[ii] + ii;
            }
        }
        cur = temp_index; // jump to this position, temp index holds index that jump most steps in next jump.
        if(cur != last){
            jumps++;
        }else{
            break;
        }
    }
    return -1;


}
};
Leo
  • 335
  • 2
  • 11
1

Thank u for asking question and providing your code. Its a very simple and descent approach :). I have used your same approach and it has passed all the test cases in one of the coding platform. Providing below small code written in java which satisfy all test cases...

public int jump(ArrayList<Integer> a) {

    int dp[]=new int[a.size()];
    if(a.size()==1  || a.size() == 0)
        return 0;
    if(a.get(0)==0)
        return -1;
    Arrays.fill(dp,Integer.MAX_VALUE);      
    dp[0]=0;
    int j=0;
    for(int i=1;i<a.size() && j<a.size();)
    {
        if(j+a.get(j)>=i && dp[j]!=Integer.MAX_VALUE)
            {
                dp[i]=Math.min(dp[j]+1,dp[i]);
                i++;
            }
       else
            j++;
    }
    if(dp[a.size()-1]==Integer.MAX_VALUE)
        return -1;
   return dp[a.size()-1];     
}
Magisch
  • 7,312
  • 9
  • 36
  • 52