DSA
Climbing Stairs
4 approaches incl. A. Recursive, B. Memoized, B. Tabulation, and more. Optimal — Time O(n), Space O(1).
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?
Practice Link
Intuition#
The last move to reach step n is either a single step from n-1 or a double step from n-2 — there's no other way to land exactly on n. So the number of distinct ways to reach n is just the sum of the ways to reach n-1 and the ways to reach n-2:
ways(n) = ways(n-1) + ways(n-2)
That's the Fibonacci recurrence in disguise, with base cases ways(0) = 1 (one way to be already at the top — take zero steps) and ways(1) = 1 (one way — a single step).
The four implementations below all solve this same recurrence, just with increasingly better complexity:
- Recursive: directly translates the recurrence into function calls. Correct, but recomputes the same subproblems exponentially many times — e.g. climbStairs(2) gets called 3 times while computing climbStairs(5).
- Memoized: caches each climbStairsUtil(idx) result the first time it's computed, so every subproblem is solved exactly once — turns the exponential recursion into O(n).
- Tabulation: builds the same values bottom-up in a dp array instead of top-down recursion, avoiding call-stack overhead entirely.
- Tabulation, space optimized: since dp[i] only ever depends on the two preceding values, there's no need to keep the whole array — two rolling variables (prev1, prev2) suffice.
Implementation#
A. Recursive Approach#
class Solution {
public:
int climbStairs(int n) {
if(n==0)
return 1;
if(n<0)
return 0;
return climbStairs(n-1) + climbStairs(n-2);
}
};
Time Complexity - O(2^n) -> TLE
Space Complexity - O(n)
B. Memoized Solution#
class Solution {
public:
int climbStairsUtil(int idx, vector<int> &memo)
{
if(idx<0)
return 0;
if(idx==0)
return 1;
if(memo[idx] != -1)
return memo[idx];
return memo[idx] = climbStairsUtil(idx-1, memo) + climbStairsUtil(idx-2, memo);
}
int climbStairs(int n) {
vector<int> memo(n+1, -1);
return climbStairsUtil(n, memo);
}
};
Time Complexity - O(n) -> overlapping cases handled via memoization
Space Complexity - O(n)
B. Tabulation Solution#
class Solution {
public:
int climbStairs(int n) {
if(n==0 || n==1)
return 1;
vector<int> dp(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];
}
};
Time Complexity - O(n)
Space Complexity - O(n)
Tabulation : Space Optimized#
class Solution {
public:
int climbStairs(int n) {
if(n==0 || n==1)
return 1;
int prev2 = 1, prev1 = 1, curr;
for(int i=2;i<=n;i++)
{
curr = prev1+prev2;
prev2 = prev1;
prev1 = curr;
}
return curr;
}
};
Time Complexity - O(n)
Space Complexity - O(1)