You are climbing a staircase. It takes n steps to reach the top.

Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?

Input: n = 2
Output: 2
Explanation: There are two ways to climb to the top.
  1. step 1 + step 1 ( take one step)
  2. step 2 ( directly go to second step)
Input: n = 3
Output: 3
Explanation: There are three ways to climb to the top.
  1. step 1 + step 1 + step 1( take one step)
  2. step 1 + step 2 ( take step 1 and then take 2 steps)
  3. step 2 + step 1 ( take 2 steps and then take 1 step)

Contents

In this approach, we will compute all possible outcomes recursively, by taking possibilities of 1 step and 2 steps from current step we are in.

import java.util.HashMap; public class ClimbingStairs { /* brute force approach */ static int climbStairsBruteForce(int n) { if(n == 0){ return 1; } if(n < 0) { return 0; } return climbStairsBruteForce(n-1) + climbStairsBruteForce(n-2); } }
Complexity Analysis:

Time complexity: Above code runs in O(2n) time where n is the input number, this is because we are creating a decision tree with two possibilities at each step.
Space complexity: O(n) as we are making recursive loops n times and this is the memory used by stack.

From the above brute force approach, we can notice that there are some overlapping problems.

For example, let's say n = 5

Climb Stairs overlapping sub problems import java.util.HashMap; public class ClimbingStairs { /* Using DP memoization*/ static int climbStairsUsingMemoization(int n) { HashMap<Integer, Integer> cache = new HashMap<>(); return climbStairsUsingMemoizationRecursive(n, cache); } static int climbStairsUsingMemoizationRecursive(int n, HashMap<Integer, Integer> cache) { if(n == 0){ return 1; } if(n < 0) { return 0; } if(cache.containsKey(n)) { return cache.get(n); } int result = climbStairsBruteForce(n-1) + climbStairsBruteForce(n-2); cache.put(n, result); return result; } }
Complexity Analysis:

Time complexity: Above code runs in O(n) time where n is the input number.
Space complexity: O(n) as we are making recursive loops n times and this is the memory used by stack and cache we are maintaining.

In this approach we will look at solving the problem using Dynamic programming using tabulation caching mechanism.
The time and memory complexity will be same as above solution using memoization, but we can notice a pattern to improve memory complexity to constant in later solution.

Intution behind this solution is, when we are at ith step, possible ways to reach that steps are possible ways to reach i -1th step plus possible ways to reach i -2nd step. This is because, If you take a look at below diagram, to reach step 2, we can either take 1 step from 1st step or two steps directly.

Climb Stairs solution using tabulation public class ClimbingStairs { /* Using DP tabulation */ static int climbStairsUsingTabulation(int n) { int[] dp = new int[n+1]; dp[0] = 1; dp[1] = 1; for(int i=2; i<=n; i++) { dp[i] = dp[i-1] + dp[i-2]; } return dp[n]; } }
Complexity Analysis:

Time complexity: Above code runs in O(n) time where n is the input number.
Space complexity: O(n) since we have a dp array with size n+1.

If we look at above DP solution using tabulation, we can see that we just need previous two values only.
If we are at step i, we only need number of ways to reach i-1th step and i-2nd step.

public class ClimbingStairs { /* Memory efficient */ static int climbStairsMemoryEfficient(int n) { int prev = 1; // start at step 0 int current = 1; // start at step 1 for(int i=1; i<n; i++) { int temp = current; current = prev+current; prev = temp; } return current; } }
Complexity Analysis:

Time complexity: Above code runs in O(n) time where n is the input number.
Space complexity: O(1) since we are only using prev, current and a temp variables.

Above implementations source code can be found at GitHub link for Java code