Dynamic programming (DP) is a problem-solving technique used in programming to optimize recursive solutions by breaking them down into simpler subproblems and storing the results of these subproblems to avoid redundant computations. This is especially useful in optimization problems, where you want to maximize or minimize certain values (e.g., finding the shortest path, minimizing costs, maximizing profit).

In Java dynamic programming can be implemented using either **memoization** (top-down approach) or **tabulation** (bottom-up approach).

## Key Concepts of Dynamic Programming

**Optimal Substructure**: The problem can be broken down into subproblems, which can be solved independently. The solution to the main problem can be constructed from the solutions to the subproblems.**Overlapping Subproblems**: The same subproblems are solved multiple times, and their results can be reused instead of recalculating.

**Example Code: Fibonacci Sequence with Dynamic Programming**

**Recursive (Inefficient) Approach:**

**Output:Â **

**Dynamic Programming Approach:**

Using a bottom-up approach, we store each calculated Fibonacci number in an array, which reduces the time complexity from O(2n)O(2^n)O(2n) to O(n)O(n)O(n).

**Output:**

**Advantages of Dynamic Programming**

- DP often reduces time complexity by storing and reusing results, which is useful for large inputs.
- Avoids redundant calculations, especially with recursive problems, improving performance and memory usage.
- Used in fields like computer science, bioinformatics, finance, and operations research for tasks like optimization and resource allocation.

**Key Features of Dynamic Programming**

- Two DP techniques – memoization (top-down approach) stores results during recursion, while tabulation (bottom-up approach) builds up solutions iteratively.
- Most DP problems are optimization problems, requiring the minimum or maximum result (e.g., shortest path, minimum cost).