Climbing Stairs (LeetCode 70): A Tiny Fibonacci in Disguise
Share Now...

Climbing Stairs (LeetCode 70): A Tiny Fibonacci in Disguise. A line‑by‑line walkthrough of a 4‑line Python solution, intuition, correctness, and faster alternatives.


TL;DR

The number of distinct ways to climb n steps when you can take 1 or 2 at a time follows the Fibonacci numbers. A 4‑line, O(n) time and O(1) space solution uses two variables to iterate the sequence.

def climbStairs(n: int) -> int:
    a, b = 1, 1   # f(0), f(1)
    for _ in range(n):
        a, b = b, a + b
    return a
  • Intuition: To reach step n, you last came from step n-1 (take 1 step) or from step n-2 (take 2 steps): f(n) = f(n-1) + f(n-2).
  • Complexity: O(n) time, O(1) space.

Problem

Each time you can climb either 1 or 2 steps. How many distinct ways to reach the top of a staircase with n steps?

Constraints: 1 ≤ n ≤ 45.


Intuition: Why Fibonacci?

Let f(n) be the number of ways to stand on step n.

  • If your last move was 1 step, you came from n-1 (there are f(n-1) ways to be there).
  • If your last move was 2 steps, you came from n-2 (there are f(n-2) ways to be there).

These are disjoint cases, so:

f(n)=f(n−1)+f(n−2)f(n) = f(n-1) + f(n-2)

Base values:

  • f(0) = 1 (one way to be at the ground: do nothing).
  • f(1) = 1 (one way: a single 1‑step).

This is exactly the Fibonacci recurrence with the shifted base. For the more common Fibonacci definition F(0)=0, F(1)=1, we have f(n) = F(n+1).


Line‑by‑Line Explanation (Python)
def climbStairs(n: int) -> int:

Defines a function that returns the count for a non‑negative integer n.

    a, b = 1, 1   # f(0), f(1)

Initializes two rolling variables:

  • a will represent f(k) and b will represent f(k+1) for the current iteration k.
  • Start with k=0: a=f(0)=1, b=f(1)=1.
    for _ in range(n):

Iterate exactly n times. After i iterations, the invariant will be: a=f(i), b=f(i+1).

        a, b = b, a + b

One atomic parallel assignment (Python evaluates the right side first):

  • New a becomes old b → shifts us from f(k) to f(k+1).
  • New b becomes old a + b → computes f(k+2) = f(k+1) + f(k).
    This advances both variables one step along the Fibonacci sequence without extra memory.
    return a

After n iterations, a = f(n) — the number of distinct ways to climb n steps.


Dry‑Run Example (n = 4)

Start: a=1 (f(0)), b=1 (f(1))

Iterationa (f(k))b (f(k+1))
0 (init)11
112
223
335
458

Return a = 5 → there are 5 distinct ways for n=4.


Correctness Argument (Loop Invariant)

Invariant: Before each iteration k (starting at 0), a = f(k) and b = f(k+1).

  • Initialization: At k=0, a=1=f(0), b=1=f(1).
  • Maintenance: The update a, b = b, a + b makes new a = f(k+1) and new b = f(k) + f(k+1) = f(k+2).
  • Termination: After n iterations, a = f(n).

Thus, return a is correct.


Complexity
  • Time: O(n) — one pass with constant work per iteration.
  • Space: O(1) — only two integers are kept, regardless of n.

Note: For the given constraint n ≤ 45, integer sizes are tiny; overflow is not a concern in Python (arbitrary precision) or 32‑bit signed ints (max result for n=45 is 1,836,311,903).


Alternatives & Optimizations
1) Fast Doubling (O(log n) time, O(1) space)

A numerically stable method that computes Fibonacci numbers using divide‑and‑conquer identities:

  • F(2k) = F(k) * [2*F(k+1) − F(k)]
  • F(2k+1) = F(k+1)^2 + F(k)^2

We return F(n+1) for f(n).

def climbStairs_fast(n: int) -> int:
    # returns (F(n), F(n+1)) with F(0)=0, F(1)=1
    def fib_pair(m: int):
        if m == 0:
            return (0, 1)
        a, b = fib_pair(m // 2)
        c = a * (2 * b - a)
        d = a * a + b * b
        if m % 2 == 0:
            return (c, d)
        else:
            return (d, c + d)

    return fib_pair(n + 1)[0]  # F(n+1) = f(n)
2) Combinatorics (Closed Form Sum)

Choosing where the 2‑steps go among (n−k) moves total when you take k double steps:

f(n)=∑k=0⌊n/2⌋(n−kk)f(n) = \sum_{k=0}^{\lfloor n/2 \rfloor} \binom{n-k}{k}

Elegant for math insights, but slower to compute directly for large n.

3) Classic DP Array (O(n) time, O(n) space)

Clear but uses extra memory:

def climbStairs_dp(n: int) -> int:
    f = [0] * (n + 2)
    f[0], f[1] = 1, 1
    for i in range(2, n + 1):
        f[i] = f[i - 1] + f[i - 2]
    return f[n]

Edge Cases & Pitfalls
  • n = 1: Returns 1 (only one 1‑step).
  • n = 2: Returns 2 (1+1, 2).
  • Off‑by‑one mistakes: If you start with (a, b) = (0, 1) you must return b at the end; with (1, 1) you return a.
  • Do not build all paths: The count grows exponentially; enumerating paths is unnecessary and expensive.

Testing (pytest)
import pytest

from typing import Callable

SOLS: list[Callable[[int], int]] = []

# drop your implementations here

def climbStairs(n: int) -> int:
    a, b = 1, 1
    for _ in range(n):
        a, b = b, a + b
    return a

SOLS.append(climbStairs)


def climbStairs_fast(n: int) -> int:
    def fib_pair(m: int):
        if m == 0:
            return (0, 1)
        a, b = fib_pair(m // 2)
        c = a * (2 * b - a)
        d = a * a + b * b
        return (c, d) if m % 2 == 0 else (d, c + d)
    return fib_pair(n + 1)[0]

SOLS.append(climbStairs_fast)

@pytest.mark.parametrize("n, expected", [
    (1, 1), (2, 2), (3, 3), (4, 5), (5, 8), (10, 89), (45, 1836311903)
])
def test_climb_stairs(n, expected):
    for f in SOLS:
        assert f(n) == expected

Variations You’ll See in Interviews
  • Different step sets: Allowed steps are {1, 3, 5} or any set S. Use dp[i] = sum(dp[i-s] for s in S if i-s >= 0).
  • Exactly k steps: Count ways to use exactly k moves — use combinatorics or 2D DP.
  • Min cost to reach the top: Each step has a cost; compute min cost with DP (min(dp[i-1], dp[i-2]) + cost[i]).

Takeaways
  • The staircase problem is Fibonacci in disguise.
  • A simple two‑variable loop gives optimal space and clear correctness.
  • Fast doubling offers a clean O(log n) upgrade when n is large.

About Connect Kreations

At Connect Kreations, we bridge the gap between technology and the community — simplifying complex ideas with practical code and hands‑on learning. If you found this useful, share it with a fellow learner and explore more guides on algorithms and interview prep.

Tags: algorithms, dynamic programming, fibonacci, interview‑prep, python, leetcode-70

Share Now...
Connect Kreations
Connect Kreations
Articles: 77