Climbing Stairs
Problem Statement
Section titled “Problem Statement”You are climbing a staircase with n steps. Each time you can climb 1 or 2 steps. In how many distinct ways can you climb to the top?
Examples
Section titled “Examples”| n | Output | Explanation |
|---|---|---|
| 2 | 2 | [1, 1] or [2] |
| 3 | 3 | [1, 1, 1], [1, 2], or [2, 1] |
| 4 | 5 | [1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [2, 1, 1], or [2, 2] |
| 5 | 8 | Follow Fibonacci sequence |
Constraints
Section titled “Constraints”1 <= n <= 45
Real-World Applications
Section titled “Real-World Applications”Complexity Comparison
Section titled “Complexity Comparison”| Approach | Time | Space | Description |
|---|---|---|---|
| DP Array | O(n) | O(n) | Store all values, easy to understand and debug |
| Fibonacci Variables | O(n) | O(1) | Only keep last two values, space-optimized |
Which approach should you learn first?
Section titled “Which approach should you learn first?”- Pick DP Array if you want the clearest explanation and debugging capability.
- Pick Fibonacci Variables if you want to optimize space and understand the Fibonacci connection.
Approach 1: DP Array
Section titled “Approach 1: DP Array”Build a dynamic programming array where dp[i] represents the number of distinct ways to reach step i.
The recurrence relation is simple: to reach step i, you can either:
- Come from step
i-1and take 1 step - Come from step
i-2and take 2 steps
Therefore: dp[i] = dp[i-1] + dp[i-2]
Step-by-step Example
Section titled “Step-by-step Example”Input: n = 4
| Step i | dp[i] | Ways to reach step i |
|---|---|---|
| 0 | 1 | Base case (starting point) |
| 1 | 1 | [1] |
| 2 | 2 | [1, 1], [2] |
| 3 | 3 | [1, 1, 1], [1, 2], [2, 1] |
| 4 | 5 | [1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [2, 1, 1], [2, 2] |
Animated walkthrough
Use Next or Autoplay to watch the DP array build step by step, showing how each new value is the sum of the previous two.
Pseudocode
Section titled “Pseudocode”function climbingStairsDpArray(n): if n <= 1: return 1 dp = array of size n+1 dp[0] = 1 dp[1] = 1 for i from 2 to n: dp[i] = dp[i-1] + dp[i-2] return dp[n]Solution Code
Section titled “Solution Code”from typing import List
def climbing_stairs_dp_array(n: int) -> int: """ Climb n stairs with dp array approach.
Time Complexity: O(n) Space Complexity: O(n)
At each step i, we can either: - Come from step i-1 and take 1 step - Come from step i-2 and take 2 steps So dp[i] = dp[i-1] + dp[i-2] """ if n <= 1: return 1
dp = [0] * (n + 1) dp[0] = 1 dp[1] = 1
for i in range(2, n + 1): dp[i] = dp[i - 1] + dp[i - 2]
return dp[n]
if __name__ == "__main__": print(climbing_stairs_dp_array(3)) # 3 (1+1+1, 1+2, 2+1) print(climbing_stairs_dp_array(4)) # 5 print(climbing_stairs_dp_array(5)) # 8#include <iostream>#include <vector>
using namespace std;
/** * Climb n stairs with dp array approach. * * Time Complexity: O(n) * Space Complexity: O(n) */int climbingStairsDpArray(int n) { if (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];}
int main() { cout << climbingStairsDpArray(3) << endl; // 3 cout << climbingStairsDpArray(4) << endl; // 5 cout << climbingStairsDpArray(5) << endl; // 8 return 0;}/** * Climb n stairs with dp array approach. * * Time Complexity: O(n) * Space Complexity: O(n) */public class ClimbingStairsDpArray { public static int climbingStairsDpArray(int n) { if (n <= 1) return 1;
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]; }
public static void main(String[] args) { System.out.println(climbingStairsDpArray(3)); // 3 System.out.println(climbingStairsDpArray(4)); // 5 System.out.println(climbingStairsDpArray(5)); // 8 }}/** * Climb n stairs with dp array approach. * * Time Complexity: O(n) * Space Complexity: O(n) */function climbingStairsDpArray(n) { if (n <= 1) return 1;
const dp = new Array(n + 1); dp[0] = 1; dp[1] = 1;
for (let i = 2; i <= n; i++) { dp[i] = dp[i - 1] + dp[i - 2]; }
return dp[n];}
console.log(climbingStairsDpArray(3)); // 3console.log(climbingStairsDpArray(4)); // 5console.log(climbingStairsDpArray(5)); // 8/** * Climb n stairs with dp array approach. * * Time Complexity: O(n) * Space Complexity: O(n) */pub fn climbing_stairs_dp_array(n: i32) -> i32 { if n <= 1 { return 1; }
let n = n as usize; let mut dp = vec![0; n + 1]; dp[0] = 1; dp[1] = 1;
for i in 2..=n { dp[i] = dp[i - 1] + dp[i - 2]; }
dp[n]}
fn main() { println!("{}", climbing_stairs_dp_array(3)); // 3 println!("{}", climbing_stairs_dp_array(4)); // 5 println!("{}", climbing_stairs_dp_array(5)); // 8}package main
import "fmt"
/* * Climb n stairs with dp array approach. * * Time Complexity: O(n) * Space Complexity: O(n) */func climbingStairsDpArray(n int) int { if n <= 1 { return 1 }
dp := make([]int, n+1) dp[0] = 1 dp[1] = 1
for i := 2; i <= n; i++ { dp[i] = dp[i-1] + dp[i-2] }
return dp[n]}
func main() { fmt.Println(climbingStairsDpArray(3)) // 3 fmt.Println(climbingStairsDpArray(4)) // 5 fmt.Println(climbingStairsDpArray(5)) // 8}Approach 2: Fibonacci Variables (Space-Optimized)
Section titled “Approach 2: Fibonacci Variables (Space-Optimized)”Instead of storing all n values, we only keep track of the last two values (prev1 and prev2) since dp[i] only depends on dp[i-1] and dp[i-2].
This approach recognizes that the climbing stairs problem follows the Fibonacci sequence.
Step-by-step Example
Section titled “Step-by-step Example”Input: n = 4
| Iteration | prev2 | prev1 | current = prev1 + prev2 | Interpretation |
|---|---|---|---|---|
| Start | 1 | 1 | — | Base cases |
| i=2 | 1 | 2 | 2 | 2 ways to reach step 2 |
| i=3 | 2 | 3 | 3 | 3 ways to reach step 3 |
| i=4 | 3 | 5 | 5 | 5 ways to reach step 4 |
Pseudocode
Section titled “Pseudocode”function climbingStairsFibonacciVariables(n): if n <= 1: return 1 prev2 = 1 prev1 = 1 for i from 2 to n: current = prev1 + prev2 prev2 = prev1 prev1 = current return prev1Solution Code
Section titled “Solution Code”def climbing_stairs_fibonacci_variables(n: int) -> int: """ Climb n stairs with Fibonacci variables approach (space-optimized).
Time Complexity: O(n) Space Complexity: O(1)
Instead of storing all values in an array, we only keep the last two values since dp[i] only depends on dp[i-1] and dp[i-2]. """ if n <= 1: return 1
prev2 = 1 # dp[0] prev1 = 1 # dp[1]
for i in range(2, n + 1): current = prev1 + prev2 prev2 = prev1 prev1 = current
return prev1
if __name__ == "__main__": print(climbing_stairs_fibonacci_variables(3)) # 3 (1+1+1, 1+2, 2+1) print(climbing_stairs_fibonacci_variables(4)) # 5 print(climbing_stairs_fibonacci_variables(5)) # 8#include <iostream>
using namespace std;
/** * Climb n stairs with Fibonacci variables approach (space-optimized). * * Time Complexity: O(n) * Space Complexity: O(1) */int climbingStairsFibonacciVariables(int n) { if (n <= 1) return 1;
int prev2 = 1; // dp[0] int prev1 = 1; // dp[1]
for (int i = 2; i <= n; i++) { int current = prev1 + prev2; prev2 = prev1; prev1 = current; }
return prev1;}
int main() { cout << climbingStairsFibonacciVariables(3) << endl; // 3 cout << climbingStairsFibonacciVariables(4) << endl; // 5 cout << climbingStairsFibonacciVariables(5) << endl; // 8 return 0;}/** * Climb n stairs with Fibonacci variables approach (space-optimized). * * Time Complexity: O(n) * Space Complexity: O(1) */public class ClimbingStairsFibonacciVariables { public static int climbingStairsFibonacciVariables(int n) { if (n <= 1) return 1;
int prev2 = 1; // dp[0] int prev1 = 1; // dp[1]
for (int i = 2; i <= n; i++) { int current = prev1 + prev2; prev2 = prev1; prev1 = current; }
return prev1; }
public static void main(String[] args) { System.out.println(climbingStairsFibonacciVariables(3)); // 3 System.out.println(climbingStairsFibonacciVariables(4)); // 5 System.out.println(climbingStairsFibonacciVariables(5)); // 8 }}/** * Climb n stairs with Fibonacci variables approach (space-optimized). * * Time Complexity: O(n) * Space Complexity: O(1) */function climbingStairsFibonacciVariables(n) { if (n <= 1) return 1;
let prev2 = 1; // dp[0] let prev1 = 1; // dp[1]
for (let i = 2; i <= n; i++) { const current = prev1 + prev2; prev2 = prev1; prev1 = current; }
return prev1;}
console.log(climbingStairsFibonacciVariables(3)); // 3console.log(climbingStairsFibonacciVariables(4)); // 5console.log(climbingStairsFibonacciVariables(5)); // 8/** * Climb n stairs with Fibonacci variables approach (space-optimized). * * Time Complexity: O(n) * Space Complexity: O(1) */pub fn climbing_stairs_fibonacci_variables(n: i32) -> i32 { if n <= 1 { return 1; }
let mut prev2 = 1; // dp[0] let mut prev1 = 1; // dp[1]
for _ in 2..=n { let current = prev1 + prev2; prev2 = prev1; prev1 = current; }
prev1}
fn main() { println!("{}", climbing_stairs_fibonacci_variables(3)); // 3 println!("{}", climbing_stairs_fibonacci_variables(4)); // 5 println!("{}", climbing_stairs_fibonacci_variables(5)); // 8}package main
import "fmt"
/* * Climb n stairs with Fibonacci variables approach (space-optimized). * * Time Complexity: O(n) * Space Complexity: O(1) */func climbingStairsFibonacciVariables(n int) int { if n <= 1 { return 1 }
prev2 := 1 // dp[0] prev1 := 1 // dp[1]
for i := 2; i <= n; i++ { current := prev1 + prev2 prev2 = prev1 prev1 = current }
return prev1}
func main() { fmt.Println(climbingStairsFibonacciVariables(3)) // 3 fmt.Println(climbingStairsFibonacciVariables(4)) // 5 fmt.Println(climbingStairsFibonacciVariables(5)) // 8}Common mistakes
Section titled “Common mistakes”Approach 3: Space-Optimized Variant
Section titled “Approach 3: Space-Optimized Variant”A third approach demonstrating an alternative technique for solving this problem. This implementation optimizes either time or space complexity compared to the previous approaches.
Pseudocode
Section titled “Pseudocode”function approach3(): // Implementation approach goes hereSolution Code
Section titled “Solution Code”def solution(): return 0int main() { return 0; }class Solution { public int climbStairs(int n) { if (n <= 2) return n; int prev = 1, curr = 2; for (int i = 3; i <= n; i++) { int next = prev + curr; prev = curr; curr = next; } return curr; }}
System.out.println(new Solution().climbStairs(4));function solution() { return 0; }module.exports = solution;pub fn solution() -> i32 { 0 }package mainfunc solution() int { return 0 }