Introduction to Dynamic Programming

What is Dynamic Programming ?

In the world of algorithm design, few techniques are as powerful and essential as Dynamic Programming (DP). Whether you’re preparing for coding interviews, solving competitive programming challenges, or building efficient software solutions, mastering DP can be a game changer.

At its core, dynamic programming is all about solving complex problems by breaking them down into simpler sub problems, and storing the solutions to avoid redundant computations.

what is dynamic programming

About Dynamic Programming

Dynamic Programming (DP) is one of the most powerful techniques in computer science for solving optimization problems.

  • It is a method used to solve complex problems by breaking them down into simpler subproblems and storing the results of these subproblems to avoid redundant computations.
  • From Fibonacci numbers to advanced graph algorithms, DP is a foundational concept every programmer must master.

It is particularly useful when a problem has the following properties:

  1. Optimal Substructure: The optimal solution of a problem can be constructed from the optimal solutions of its subproblems.
  2. Overlapping Subproblems: The problem can be broken down into subproblems which are reused several times.

Top Down vs Bottom Up Approaches

There are 2 primary approaches in DP:

1. Top Down (Memoization)

This approach uses recursion. We start solving the problem by breaking it into smaller subproblems and storing their results in a cache (usually an array or map) to avoid recomputation.

Code:

Run

// Top-Down Fibonacci (Memoization)
public class FibonacciMemo {
    static int[] dp = new int[1000];

    static int fib(int n) {
        if (n <= 1)
            return n;
        if (dp[n] != 0)
            return dp[n];
        dp[n] = fib(n - 1) + fib(n - 2);
        return dp[n];
    }

    public static void main(String[] args) {
        System.out.println(fib(10)); // Output: 55
    }
}

2. Bottom Up (Tabulation)

This approach solves all related subproblems first and uses their answers to build up solutions to bigger subproblems.

Run
// Bottom-Up Fibonacci (Tabulation)
public class FibonacciTabulation {
    static int fib(int n) {
        int[] dp = new int[n + 1];
        dp[0] = 0;
        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(fib(10)); // Output: 55
    }
}

Prime Course Trailer

Related Banners

Get PrepInsta Prime & get Access to all 200+ courses offered by PrepInsta in One Subscription

Types of Problems Solved Using Dynamic Programming

1. Fibonacci Numbers

Calculates the nth number in the Fibonacci sequence using previously computed values to avoid redundant recursion.

2. Knapsack Problem

Selects items with maximum value under a weight constraint—solved using 0/1 or fractional strategies.

3. Longest Common Subsequence (LCS)

Finds the longest sequence present in the same order in both strings (not necessarily contiguous).

4. Matrix Chain

Multiplication
Determines the most efficient way to multiply a chain of matrices by minimizing scalar multiplications.

5. Partition Problems

Decides whether an array can be divided into two subsets with equal sums or into parts with specific conditions.

6. Subset Sum

Checks if there’s a subset of a given set whose elements add up to a specific sum.

7. Coin Change

Finds the number of ways to make change or the minimum number of coins required for a given amount.

8. Edit Distance

Measures how many operations (insert, delete, replace) are needed to convert one string into another.

9. Rod Cutting

Maximizes profit by cutting a rod into pieces and selling them based on given prices.

10. Catalan Numbers

Solves combinatorial problems like valid parenthesis combinations, binary tree structures, etc.

Some Common Dynamic Programming Problems Explained

1. 0/1 Knapsack Problem

Given weights and values of n items, put these items in a knapsack of capacity W to get the maximum total value in the knapsack.

dp[i][w] = max(dp[i-1][w], dp[i-1][w - weight[i]] + value[i])
Run
public class Knapsack01 {
    static int knapsack(int[] wt, int[] val, int W, int n) {
        int[][] dp = new int[n + 1][W + 1];

        for (int i = 1; i <= n; i++) {
            for (int w = 1; w <= W; w++) {
                if (wt[i - 1] <= w)
                    dp[i][w] = Math.max(val[i - 1] + dp[i - 1][w - wt[i - 1]], dp[i - 1][w]);
                else
                    dp[i][w] = dp[i - 1][w];
            }
        }

        return dp[n][W];
    }

    public static void main(String[] args) {
        int[] wt = { 1, 3, 4, 5 };
        int[] val = { 1, 4, 5, 7 };
        int W = 7;
        int n = wt.length;
        System.out.println(knapsack(wt, val, W, n)); // Output: 9
    }
}

2. Longest Common Subsequence (LCS)

Given two strings, find the length of the longest subsequence present in both.

DP Relation:

if (X[i] == Y[j])
    dp[i][j] = 1 + dp[i-1][j-1]
else
    dp[i][j] = max(dp[i-1][j], dp[i][j-1])

Run

public class LCS {
    static int lcs(String X, String Y) {
        int m = X.length(), n = Y.length();
        int[][] dp = new int[m + 1][n + 1];

        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (X.charAt(i - 1) == Y.charAt(j - 1))
                    dp[i][j] = 1 + dp[i - 1][j - 1];
                else
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
            }
        }

        return dp[m][n];
    }

    public static void main(String[] args) {
        System.out.println(lcs("AGGTAB", "GXTXAYB")); // Output: 4
    }
}

Memoization vs Tabulation in Dynamic Programming

CriteriaMemoizationTabulation
StyleTop-down (recursive)Bottom-up (iterative)
Ease of WritingSimpler, intuitiveMore control over flow
PerformanceSlightly more overhead (stack)Usually faster
Memory UsageCan be worse (due to recursion)More predictable

Use memoization for tree/graph DP, and tabulation when recursion depth might cause stack overflow or when optimization is required.

Common Dynamic Programming Problems and their Complexity

ProblemTime ComplexitySpace Complexity
Fibonacci (Basic)O(n)O(1)
0/1 KnapsackO(nW)O(nW)
Longest Common Subseq.O(mn)O(mn)
Edit DistanceO(mn)O(mn)
Matrix Chain Multip.O(n^3)O(n^2)
Subset SumO(n*sum)O(n*sum)

Real Life Applications of Dynamic Programming

  1. Route optimization in Google Maps
  2. Bioinformatics (DNA sequence alignment)
  3. Financial modeling and portfolio optimization
  4. Spell checkers using edit distance
  5. Game AI to find best move using DP
  6. Text Justification in document formatting

Tips for Solving DP Problems

  1. Recognize the problem type – Optimization or counting?
  2. Identify the recurrence – Try to express the relation between subproblems.
  3. Choose an approach – Top-down or Bottom-up.
  4. Think about space – Can you optimize?
  5. Trace your table – Backtrack to understand how values are built.
  6. Practice classic patterns – LCS, Knapsack, LIS, etc.

FAQ's related to Dynamic Programming

Answer:

Dynamic Programming is a method used in computer science to solve complex problems by breaking them down into simpler subproblems, solving each subproblem just once, and storing their results (usually using memoization or tabulation) to avoid redundant computations.

Answer:

Use DP when a problem has overlapping subproblems (solving the same subproblem multiple times) and optimal substructure (optimal solution can be formed using optimal solutions of subproblems).

Answer:

  • Memoization is a top down recursive approach with caching.
  • Tabulation is a bottom up iterative approach using a table to build the solution step by step.

Answer:

Some common DP problems include:

  1. Fibonacci Series
  2. 0/1 Knapsack
  3. Longest Common Subsequence
  4. Edit Distance
  5. Matrix Chain Multiplication
  6. Subset Sum

Answer:

No. While DP reduces time complexity significantly, it may use more space. It’s ideal only when the problem has overlapping sub problems and optimal substructure. For problems without these properties, other algorithms may be better.