← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

Dynamic Programming

Algorithms PHP 5.0+ Advanced
debt(d7/e3/b3/t5)
d7 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'only careful code review or runtime testing' (d7). The detection_hints list blackfire and xdebug as tools, but these only reveal exponential slowness at runtime under profiling — there is no static analysis that identifies overlapping subproblems. The automated flag is explicitly 'no', and the code pattern (recursive function with overlapping subproblems) requires a human reviewer to recognise the structural property. The problem is silent until scale reveals it.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix describes adding memoization (an array keyed by input) to an existing recursive function, or switching to tabulation. This is more than a one-line patch — it requires identifying the recurrence, adding a cache structure, and adjusting the recursive calls — but it is contained within a single function or component and does not require cross-cutting changes.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3). DP applies to specific algorithmic functions (web/cli contexts) rather than being a system-wide architectural choice. Once a DP solution is correctly implemented, the rest of the codebase is unaffected; the burden is paying attention during the design of that one algorithm. The common mistake of allocating a full 2D table adds localised memory waste but does not propagate across the system.

t5 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'notable trap' (t5). The misconception field states that developers commonly believe DP always requires a multidimensional array, when many problems only need O(n) or O(1) space. Additionally, common_mistakes highlight confusing DP with greedy algorithms and failing to identify the recurrence relation first. These are well-documented gotchas that most developers encounter, making this a notable but learnable trap rather than a catastrophic one.

About DEBT scoring →

Also Known As

DP memoisation tabulation

TL;DR

An optimisation technique that solves problems by breaking them into overlapping subproblems, storing results to avoid redundant computation.

Explanation

Dynamic programming applies when a problem has optimal substructure (optimal solution built from optimal subproblems) and overlapping subproblems (same subproblem solved multiple times). Two approaches: top-down memoisation (recursive with a cache) and bottom-up tabulation (iterative, fill a table). Classic examples: Fibonacci, longest common subsequence, knapsack problem. In web development, DP appears in query result caching, diff algorithms, and compiler optimisations.

Diagram

flowchart TD
    subgraph Naive Fibonacci - Exponential
        F5[fib 5] --> F4[fib 4] & F3A[fib 3]
        F4 --> F3B[fib 3] & F2A[fib 2]
        F3A --> F2B[fib 2] & F1A[fib 1]
        F3B --> F2C[fib 2] & F1B[fib 1]
        note1[Same subproblems<br/>calculated repeatedly]
    end
    subgraph Memoised - Linear
        M5[fib 5] --> M4[fib 4] --> M3[fib 3] --> M2[fib 2] --> M1[fib 1]
        CACHE[(Memo cache<br/>results reused)]
        M2 & M3 & M4 --> CACHE
    end
style CACHE fill:#238636,color:#fff
style note1 fill:#f85149,color:#fff

Common Misconception

Dynamic programming always requires a multidimensional array — many DP problems only need O(n) or O(1) space by keeping only the last few rows.

Why It Matters

Recognising that an exponential naive solution has overlapping subproblems lets you transform it to polynomial time — the difference between unusable and instant at scale.

Common Mistakes

  • Naive recursion without memoisation for Fibonacci or similar — O(2ⁿ) instead of O(n).
  • Allocating a full 2D DP table when only the previous row is needed — wastes O(n²) memory.
  • Not identifying the recurrence relation before coding — DP without the relation is just guessing.
  • Confusing DP with greedy algorithms — greedy makes locally optimal choices, DP explores all subproblems.

Code Examples

✗ Vulnerable
// Naive Fibonacci — O(2ⁿ) — recalculates same values exponentially:
function fib(int $n): int {
    if ($n <= 1) return $n;
    return fib($n - 1) + fib($n - 2); // fib(40) = ~1 billion calls
}
✓ Fixed
// Memoised — O(n) time, O(n) space:
function fib(int $n, array &$memo = []): int {
    if ($n <= 1) return $n;
    return $memo[$n] ??= fib($n - 1, $memo) + fib($n - 2, $memo);
}

// Bottom-up tabulation — O(n) time, O(1) space:
function fibTab(int $n): int {
    [$a, $b] = [0, 1];
    for ($i = 2; $i <= $n; $i++) [$a, $b] = [$b, $a + $b];
    return $b;
}

Added 15 Mar 2026
Edited 22 Mar 2026
Views 61
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
1 ping T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 2 pings W 2 pings T 1 ping F 3 pings S 1 ping S 3 pings M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S 0 pings S 0 pings M 1 ping T 0 pings W 0 pings T 0 pings F 2 pings S 1 ping S 0 pings M 0 pings T 0 pings W
No pings yet today
No pings yesterday
Scrapy 11 Amazonbot 9 Perplexity 8 SEMrush 5 Google 5 Ahrefs 4 Unknown AI 2 Claude 2 Bing 2 ChatGPT 2 Majestic 1
crawler 46 crawler_json 5
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: High
⚡ Quick Fix
If a recursive solution recomputes the same subproblems, add memoization (top-down) or switch to tabulation (bottom-up) — store results in an array keyed by input
📦 Applies To
PHP 5.0+ web cli
🔗 Prerequisites
🔍 Detection Hints
Recursive function with overlapping subproblems and no memoization; exponential time for Fibonacci-like problems
Auto-detectable: ✗ No blackfire xdebug
⚠ Related Problems
🤖 AI Agent
Confidence: Low False Positives: High ✗ Manual fix Fix: High Context: Function Tests: Update


✓ schema.org compliant