Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using only 1, 2, 3 steps reach to nth step

Tags:

java

algorithm

I was doing an online interview some days back and came across this task that we can reach the nth step by using only steps 1 or 2 or 3.

Updated Question: A child is running up a staircase with n steps and can hop either 1 step, 2 steps, or 3 steps at a time. Implement a method to count how many possible ways the child can run up the stairs.

This is my solution using dynamic programming. But during the interview, I saw that there were 6 hidden test cases that were failing.

public static long countWays(int n)
    {
        if(n==0 || n==1) return 1;

        long[] res = new long[n + 1];
        res[0] = 1;
        res[1] = 1;
        res[2] = 2;
 
        for (int i = 3; i <= n; i++)
            res[i] = res[i - 1] + res[i - 2]
                     + res[i - 3];
 
        return res[n];
    }
 

During the interview, only 5 test cases were passing out of 11. The remaining 6 are hidden test cases.

The range for n is 0 to 10 power 8.

I was not able to understand where I was doing a mistake, already this code is in O(n) time complexity. Is there a better way to do this or am I missing something?

like image 760
learner Avatar asked Mar 24 '21 22:03

learner


People also ask

How many ways are there to reach the nth stair?

So consider the stairs has 2 steps. Then there 2 possible ways, either you step directly to 2nd step or the first step to 1st step and then to 2nd. Similarly, we need to count the ways to reach the nth stair using steps 1, 2, or 3.

How do you store the number of ways to reach nth step?

Then in each recursive call, go to step i+1, i+2, and i+3. When you reach the nth step increment the counter. This way in the end the counter stores the number of ways to reach the nth step. But this step recomputes the same problems again and again.

How to count the number of steps in a for loop?

1 Create an array count [] of size equal to the total number of steps + 1 with all elements initialized to 0 and initialize the first element i.e. ... 2 Initialize a variable no_ways = 0 inside the for loop and everytime starting from 0 for the new ways of climbing the stairs. 3 Add count [i – x [j]] to no_ways only if i – x [j] ≥ 0. More items...

How do you calculate the number of ways to reach ith step?

Then the number of ways to reach ith step is from i-1 step, i-2 step, or i-3 step. So formally speaking, ways [i] = ways [i-1] + ways [i-2] + ways [i-3], using this recursive formula.


1 Answers

You can write down the recurrence relation in this problem

Sk = Sk-1 + Sk-2 + Sk-3

in the following matrix form:

| S[k]   |   | 1  1  1 |   | S[k-1] |   
| S[k-1] | = | 1  0  0 | * | S[k-2] |
| S[k-2] |   | 0  1  0 |   | S[k-3] |   

Which means that the k-th power of the matrix can quickly give you Sk:

            k
| 1  1  1 |     | S[2] |   | S[k+2] | 
| 1  0  0 |   * | S[1] | = | S[k+1] |
| 0  1  0 |     | S[0] |   | S[k]   |

So to solve this problem you basically need to find the n-th power of this matrix.

You can raise something to the n-th power in O(log n) time using the exponentiation by squaring algorithm.

Another useful observation is that you need only 3 numbers Sk, Sk-1 and Sk-2 to the represent the k-th power of the matrix:

            k
| 1  1  1 |     | S[k] + S[k-1] + S[k-2]    S[k] + S[k-1]      S[k]   |
| 1  0  0 |   = | S[k]                      S[k-1] + S[k-2]    S[k-1] |
| 0  1  0 |     | S[k-1]                    S[k] - S[k-1]      S[k-2] |

And from this, by multiplying k-th and m-th powers of the matrix you can get the following relations:

Sk+m = SkSm-2 + Sk-2Sm + Sk-1Sm-2 + Sk-2Sm-1 + Sk-2Sm-2 + Sk-1Sm-1
Sk+m-1 = SkSm-1 + Sk-1Sm + Sk-1Sm-1 + Sk-2Sm-2
Sk+m-2 = Sk-1Sm-2 + Sk-2Sm-1 + SkSmSk-1Sm-1

Putting all of this together into code you get the following solution:

public class Solution {
    private static final int M = 1_000_000_007;

    // The set of equations for S[k+m], S[k+m-1], S[k+m-2]
    // a[t] is S[k-t] and b[t] is S[m-t]
    private static long[] mul(long[] a, long[] b) {
        long r0110 = a[0]*b[1] + a[1]*b[0];
        long r0011 = a[0]*b[0] + a[1]*b[1];
        return new long[] {
            (a[0]*b[2] + a[2]*b[0] + r0110 + r0011) % M,
            (a[1]*b[2] + a[2]*b[1] + r0011) % M,
            (r0110 + a[2]*b[2] - a[1]*b[1]) % M
        };
    }

    public static long countWays(int n) {
        long[] result = {1, 0, 0};
        long[] square = {1, 0, 0};
        // Exponentiation by squaring
        for (int i = n; i != 0; i /= 2) {
            if (i % 2 == 1) result = mul(result, square);
            square = mul(square, square);
        }
        return result[0];
    }
}
like image 186
Kolmar Avatar answered Sep 24 '22 12:09

Kolmar