cconnected.
Understand the pattern. Find your own way.Find your starting point
Your learning feed/Idea 20 of 218
Ideas this builds on
Recursion20 / 218

A call tree is a record of work

Picture

A recursion tree shows which question asked which smaller questions. Some trees represent distinct choices you must explore. Others contain repeated copies of the very same question. Learning to tell those apart is the bridge from recursion to dynamic programming.

Predict

You can climb one or two steps at a time. While counting routes up four steps, can “three steps left” and “two steps left” both eventually ask “one step left”?

Reveal the reasoning

Yes. Different histories reach an identical remaining question. If the allowed steps never depend on history, the number of continuations from one step left is reusable.

Go deeper: distinguish occurrences from states
ways(4)
├── ways(3)
│   ├── ways(2)
│   │   ├── ways(1)
│   │   └── ways(0)
│   └── ways(1)
└── ways(2)        ← same question as above
    ├── ways(1)
    └── ways(0)
def ways(remaining):
    if remaining == 0:
        return 1
    if remaining < 0:
        return 0
    return ways(remaining - 1) + ways(remaining - 2)

assert ways(4) == 5
assert ways(0) == 1

Zero remaining steps has one completion: choose no more moves. Negative remaining steps has no completion. The first choices, one step and two steps, are disjoint; adding their counts does not double-count an individual sequence.

The plain recursion has exponentially many call occurrences, with O(2**n) a simple upper bound. Its maximum active depth is O(n), not the total number of calls. There are only n+1 nonnegative remaining-step states.

Merge repeated states conceptually and the dependency picture becomes a directed acyclic graph. Caching stores one answer per state, but both callers still use that count; you do not throw away one route’s contribution.

Analogy limit: not every recursion benefits from caching. A tree-height calculation on a normal tree visits each node once already. And listing every staircase sequence still requires constructing every requested output.

Change one rule

You may not take a two-step move immediately after another two-step move. Is remaining still enough?

Check the variation

No. Whether the previous move had size two changes the legal next moves. Add that information to the state, such as (remaining, previous_was_two).

Connect

DP state formalizes which repeated questions can merge. Backtracking will preserve distinct constructions. 1D DP practices a one-coordinate contract with a different objective.