Problem
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?
OR
There are n stairs, a person standing at the bottom wants to reach the top. The person can climb either 1 stair or 2 stairs at a time. Count the number of ways, the person can reach the top.
Examples
Example 1:
|
|
Example 2:
|
|
Example 3:
|
|
Example 4:
|
|
Solution
Video explanation
Here is the video explaining this method in detail. Please check it out:
Method 1 - Backtracking
This approach uses Depth-First Search (DFS) or backtracking to explore all possible paths to climb the staircase. At each step, the function recursively adds either 1 step or 2 steps, terminating when the step count either reaches or exceeds n
.
Here si the approach:
- Start the recursion (DFS) from step
0
. - At each step:
- Add 1 step to the current step and call the function recursively.
- Add 2 steps to the current step and call the function recursively.
- Base Cases:
- If
current_step == n
, the path is valid, so return1
. - If
current_step > n
, the path exceeds the total steps, so return0
.
- If
- Accumulate valid paths for both choices (taking 1 step or 2 steps).
Here is how the recursion tree will look like:
graph TD; A("0:4") ---|1 step| B(1) A ---|2 steps| C(2) B ---|1 step| D(2) B ---|2 steps| E(3) C ---|1 step| F(3) C ---|2 steps| G(4):::green D ---|1 step| H(3) D ---|2 steps| I(4):::green E ---|1 step| J(4):::green E ---|2 steps| K(5):::red F ---|1 step| L(4):::green F ---|2 steps| M(5):::red H ---|1 step| N(4):::green H ---|2 steps| O(5):::red classDef green fill:#3CB371,stroke:#000,stroke-width:1px,color:#fff; classDef red fill:#FF0000,stroke:#000,stroke-width:1px,color:#fff;
As, you can see the total number of green or valid nodes are 5.
Code
|
|
|
|
Complexity
- ⏰ Time complexity:
O(2^n)
. The total number of paths is roughly2^n
because two recursive calls are made at each step. - 🧺 Space complexity:
O(n)
, as the recursion stack can grow up ton
levels deep.
Method 2 - Recursion
We can easily find recursive nature in above problem.
Lets take n = 2, then we have 2 ways - either take 1 step twice or 2 steps in one go.
For n = 3, we have 3 ways:
- One Step at a time
- Two-step then one step
- One step then Two-step
For n = 4, we have 5 ways: (1, 1, 1, 1), (2, 2), (1, 1, 2), (2, 1, 1), (1, 2, 1)
Now, lets take n = 6, and try to get the algorithm.
So in the next step, we need to calculate the number of ways taken to raise 5 steps and 4 steps.
We can build full tree for the steps taken as below (not complete for clarity):
Code
|
|
|
|
Complexity
- ⏰ Time complexity:
O(2^n)
, because overlapping subproblems are recomputed multiple times. - 🧺 Space complexity:
O(n)
due to recursion stack.
Method 3 - Top Down DP
The naive recursive approach recalculates overlapping subproblems multiple times, leading to inefficiency. By using a memoisation table (cache), you can store results of previously computed subproblems to avoid redundant calculations.
Here is the approach:
- Use a cache (
HashMap
or dictionary) to store results for each step:- If the result for
n
is already computed, retrieve it from the cache. - Otherwise, compute
ways(n)
recursively:ways(n) = ways(n-1) + ways(n-2)
- Save the result for
n
in the cache for future use.
- If the result for
Code
|
|
|
|
Complexity
- ⏰ Time complexity:
O(n)
- 🧺 Space complexity:
O(n)
Method 4 - Bottom UP DP
Instead of recursion, build the solution iteratively using a dp
table. Once base cases are solved (dp[1] = 1, dp[2] = 2
), compute the number of ways for each step up to n
by combining results for the previous two steps. This avoids recursion overhead and ensures every subproblem is solved sequentially.
Here is the approach:
- Initialise a
dp
array of sizen+1
(to store results for steps1
ton
). - Populate the base cases:
dp[1] = 1
dp[2] = 2
.
- Use the recurrence relation iteratively:
dp[i] = dp[i-1] + dp[i-2]
- Return the value stored at
dp[n]
.
Code
|
|
|
|
Complexity
- ⏰ Time complexity:
O(n)
- 🧺 Space complexity:
O(n)
for using the dp tale
Method 5 - Space efficient Bottom up DP
While the bottom-up DP uses a dp
table, observe that only the last two values, dp[i-1]
and dp[i-2]
, are needed to compute dp[i]
. This allows us to optimise space by storing only two variables (prev1
and prev2
) instead of maintaining an entire table.
Here is the approach:
- Initialise two variables:
prev1
holdsdp[i-1]
(starting withdp[2]
= 2).prev2
holdsdp[i-2]
(starting withdp[1]
= 1).
- Iteratively compute the current value using the relation:
curr = prev1 + prev2
- Shift the variables:
prev2 = prev1
prev1 = curr
.
- Return the final value (
prev1
).
Code
|
|
|
|
Complexity
- ⏰ Time complexity:
O(n)
. We iterate through all steps from3
ton
. - 🧺 Space complexity:
O(1)
. Uses only two variables (prev1
andprev2
), avoiding the need for a DP table.
Method 6- Using Fibonacci Numbers
The number of ways to reach the n-th stair on a staircase depends on whether you can take one step at a time (from the (n-1)th stair) or two steps at a time (from the (n-2)th stair). We’ll represent this total number of ways to reach the n-th stair as ways(n)
.
|
|
This is actually formula for generating nth fibonacci number.
But notice one thing that ways(n)
is equal to fib(n+1)
, hence we can reuse fib(n)
function.
|
|
Code
|
|
Complexity
- ⏰ Time complexity:
O(n)
. (It can be optimized to work in O(Logn) time using matrix approach) - 🧺 Space complexity:
O(n)