Skip to main content

dynamic-programming

Optimization technique that solves complex problems by breaking them into overlapping subproblems, solving each once, and storing results to avoid redundant computation

Ir a la instalación

Datos de origen

Repositorio
lev-os/agents
Última actividad en el origen
7 de marzo de 2026 a las 00:14
Idioma detectado de SKILL.md
inglés
Estrellas
21
Forks
2

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
Dynamic Programming
description
Optimization technique that solves complex problems by breaking them into overlapping subproblems, solving each once, and storing results to avoid redundant computation
# Dynamic Programming Algorithm Paradigm ## What It Is An optimization technique that solves complex problems by breaking them into overlapping subproblems, solving each subproblem once, and storing the results to avoid redundant computation. Unlike divide-and-conquer where subproblems are independent, DP exploits the overlap by remembering solutions (memoization or tabulation) to transform exponential-time recursive algorithms into polynomial-time solutions. ## When to Use It - Problem has **overlapping subproblems** (same subproblem solved multiple times) - Problem exhibits **optimal substructure** (optimal solution contains optimal solutions to subproblems) - Recursive solution exists but has exponential time due to repeated computation - Need to find optimal value (min/max) or count all possible solutions - Problem involves sequences, trees, graphs with state-dependent decisions - Trade space for time is acceptable (store intermediate results) ## Execution Steps ### 1. Clarify the State Identify what variables fully describe a subproblem. State should be minimal but complete - enough to uniquely identify each subproblem. Common state patterns: position in array, remaining capacity, substring boundaries, node in graph. **Action**: Ask "What parameters change in the recursion?" Write state as `dp[i]`, `dp[i][j]`, or `dp[state_tuple]`. Example: Fibonacci → `dp[n]`; Knapsack → `dp[item][capacity]`. ### 2. Define the Recurrence (State Transition) Express the solution for state `dp[i]` in terms of smaller/simpler states. This is the heart of DP. Identify the decision at each step and how choices affect the state. **Action**: Write the recurrence relation mathematically. Example: `dp[i] = min(dp[i-1] + cost1, dp[i-2] + cost2)`. Ensure base cases are clearly defined (typically `dp[0]` or boundary conditions). ### 3. Choose Implementation Approach **Top-Down (Memoization)**: Start from the problem, recurse naturally, cache results in a memo table. Easier to write, only computes needed subproblems. **Bottom-Up (Tabulation)**: Start from base cases, iteratively fill table in topological order. More efficient (no recursion overhead), easier to optimize space. **Action**: For interview/rapid prototyping → top-down. For production/performance → bottom-up. Consider space optimization (often reduce from O(n²) to O(n) by keeping only last row). ### 4. Identify the Choices At each state, what decisions can you make? For optimization problems: which option to take? For counting: how many ways to proceed? Choices determine the recurrence structure. **Action**: List all valid transitions from current state. Example: Coin change → try each coin denomination; Longest increasing subsequence → include or skip current element. ### 5. Code the Solution Implement the recurrence with proper base cases. For top-down: add memoization decorator or explicit cache checks. For bottom-up: initialize table, iterate in correct order (ensure dependencies computed first), extract final answer. **Action**: Write base case first, then recursive/iterative logic, finally return `dp[target_state]`. Test with small examples manually before running. ### 6. Analyze and Optimize Calculate time complexity (usually O(num_states × transitions_per_state)) and space complexity. Look for space optimization opportunities: rolling arrays, state compression, dimension reduction. **Action**: Measure runtime on test cases. Profile memory usage. Apply space optimizations if needed (e.g., Fibonacci from O(n) space to O(1)). ## Real-World Applications **Finance & Operations Research** - Portfolio optimization: maximize returns given constraints - Resource allocation: knapsack variants for budget distribution - Inventory management: optimal ordering policies over time **Bioinformatics** - Sequence alignment (Needleman-Wunsch, Smith-Waterman): DNA/protein matching - RNA folding prediction: secondary structure optimization - Phylogenetic tree construction: evolutionary distance minimization **Text Processing** - Edit distance (Levenshtein): spell checkers, DNA matching, diff tools - Longest common subsequence: version control, plagiarism detection - Word break problem: natural language processing, search query parsing **Game Theory & AI** - Optimal game strategy: chess endgames, poker decision trees - Reinforcement learning: value iteration, policy optimization (Bellman equations) - Path planning: robot navigation with state-dependent costs **Computer Graphics & Vision** - Image segmentation: seam carving, optimal path finding - Video encoding: motion estimation, compression optimization - Texture synthesis: dynamic texture generation **Compiler Optimization** - Code generation: register allocation, instruction scheduling - Matrix chain multiplication: optimal parenthesization for expression evaluation - Optimal binary search trees: minimize expected search time ## Anti-Patterns **Using DP when subproblems don't overlap** → Wastes space storing unused results; use divide-and-conquer instead. **Wrong state definition** → Leads to incorrect recurrence or exponential state space; rethink what truly defines a subproblem. **Missing base cases** → Causes infinite recursion or index errors; always handle boundary conditions explicitly. **Computing states in wrong order (bottom-up)** → Accesses uninitialized values; ensure topological order respects dependencies. **Not checking for optimality structure** → DP won't work if optimal solution doesn't contain optimal subsolutions; verify this property first. **Over-engineering the recurrence** → Including unnecessary state dimensions bloats space complexity; keep state minimal. ## Success Metrics - Time complexity reduction from exponential to polynomial (e.g., O(2ⁿ) → O(n²)) - Correctness on all test cases including edge cases (empty input, single element) - Space efficiency (can O(n²) be reduced to O(n)?) - Code clarity (recurrence relation obvious from implementation?) - Performance on large inputs (n=10,000+) vs. recursive baseline ## Related Frameworks - **Divide and Conquer**: For non-overlapping subproblems (convert DP to D&C by removing memoization) - **Greedy Algorithms**: When local optimal choices suffice (DP guarantees global optimum) - **Backtracking**: For constraint satisfaction without optimization - **Memoization Pattern**: General caching technique beyond DP - **Bellman-Ford, Dijkstra**: Graph shortest paths using DP principles ## Common Pitfalls - Forgetting to initialize DP table with sentinel values (infinity for min, zero for max) - Off-by-one errors in state indices (especially for substrings/subarrays) - Not handling negative numbers/weights when problem assumes non-negative - Confusing "optimal substructure" with "subproblem independence" (DP needs former, not latter) - Implementing top-down without memoization (defeating the purpose) - Using recursion with memoization for extremely deep problems (stack overflow) ## Tools & Resources - **Visualization**: Dynamic Programming Visualizer (algorithm-visualizer.org), LeetCode's DP Explorer - **Practice Platforms**: LeetCode (DP tag ~400 problems), Codeforces DP category, Project Euler - **Books**: "Dynamic Programming for Coding Interviews" (Meenakshi), "Algorithms" (Dasgupta, Papadimitriou, Vazirani) - **Pattern Guides**: "Dynamic Programming Patterns" (14 common patterns: Fibonacci, 0/1 Knapsack, Unbounded Knapsack, LCS, LIS, Palindromes, etc.) - **Debugging**: Print DP table after computation to verify values, use small test cases (n≤5) for manual checking ## Classic Problem Patterns **Linear DP**: Fibonacci, climbing stairs, house robber (1D state, O(n)) **Grid DP**: Unique paths, minimum path sum, edit distance (2D state, O(n×m)) **Knapsack Variants**: 0/1 knapsack, unbounded knapsack, subset sum (2D → 1D optimization possible) **Interval DP**: Matrix chain multiplication, palindrome partitioning (O(n³) with 2 endpoints as state) **Tree DP**: House robber III, binary tree cameras (state = node + subtree status) **Bitmask DP**: Traveling salesman, subset enumeration (state = visited set as bitmask) --- *Framework Type*: Algorithm Design Paradigm *Domain*: Computer Science, Optimization *Practitioner Score*: 10/10 - Essential for technical interviews, powers production systems at scale *Complexity*: Medium-High - Requires recurrence relation insight and state design skills *Prerequisites*: Recursion, mathematical induction, basic combinatorics, time/space complexity analysis
Ver en GitHub