Recursion and Memoization

Recursion vs Dynamic Programming

How does dynamic programming differ from plain recursion, and when should I use it?

Abstract art representing computer programming

Dynamic programming is an optimization technique that builds upon the idea of recursion. It is used to solve problems that have overlapping subproblems and optimal substructure. While plain recursion can lead to redundant calculations, dynamic programming aims to eliminate this redundancy and improve efficiency.

Key differences between dynamic programming and plain recursion:

  1. Memoization: Dynamic programming often involves memoization, which is the process of storing the results of expensive function calls and returning the cached result when the same inputs occur again. This eliminates the need to recompute the same subproblems multiple times.
  2. Tabulation: Dynamic programming can also be implemented using tabulation, where the results of subproblems are computed in a bottom-up manner and stored in a table. This avoids the overhead of recursive function calls and can be more efficient in terms of memory usage.
  3. Optimal substructure: Dynamic programming is applicable when the problem has an optimal substructure, meaning that the optimal solution to the problem can be constructed from the optimal solutions of its subproblems.
  4. Overlapping subproblems: Dynamic programming is effective when the problem has overlapping subproblems, i.e., when the same subproblems are solved multiple times during the recursive process.

When to use dynamic programming:

  • When the problem has overlapping subproblems and optimal substructure.
  • When plain recursion leads to redundant calculations and inefficient solutions.
  • When the problem size is large, and the recursive solution is too slow or exceeds the stack limit.

Let's consider the classic example of the Fibonacci sequence to illustrate the difference:

#include <iostream>
#include <unordered_map>

// Plain recursive solution
int fibonacciRecursive(int n) {
  if (n <= 1) {
    return n;
  }
  return fibonacciRecursive(n - 1)
    + fibonacciRecursive(n - 2);
}

// Dynamic programming solution with memoization
std::unordered_map<int, int> memoMap;

int fibonacciMemoized(int n) {
  if (memoMap.find(n) != memoMap.end()) {
    return memoMap[n];
  }
  if (n <= 1) {
    return n;
  }
  int result = fibonacciMemoized(n - 1)
    + fibonacciMemoized(n - 2);
  memoMap[n] = result;
  return result;
}

int main() {
  int n = 40;
  std::cout << "Fibonacci (recursive): "
    << fibonacciRecursive(n) << "\n";
  std::cout << "Fibonacci (memoized): "
    << fibonacciMemoized(n) << "\n";
}
Fibonacci (recursive): 102334155
Fibonacci (memoized): 102334155

In the plain recursive solution, the fibonacciRecursive function calculates the Fibonacci number by recursively calling itself. However, this leads to redundant calculations, as the same Fibonacci numbers are computed multiple times.

On the other hand, the dynamic programming solution with memoization (fibonacciMemoized) uses an unordered map (memoMap) to store the previously computed Fibonacci numbers. Before recursively calling itself, it checks if the result is already memoized. If so, it returns the memoized value, avoiding redundant calculations.

The dynamic programming solution is much more efficient, especially for larger values of n. It eliminates the redundant calculations and significantly reduces the time complexity from exponential to linear.

In summary, dynamic programming is a powerful technique that can be used to optimize recursive solutions by eliminating redundant calculations through memoization or tabulation. It is particularly useful when the problem has overlapping subproblems and optimal substructure. By applying dynamic programming, you can improve the efficiency and scalability of your solutions.

Answers to questions are automatically generated and may not have been reviewed.

A computer programmer
Part of the course:

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Free, unlimited access

This course includes:

  • 125 Lessons
  • 550+ Code Samples
  • 96% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved