Code360 powered by Coding Ninjas X Naukri.com. Code360 powered by Coding Ninjas X Naukri.com
Table of contents
1.
Introduction
2.
What is Dynamic Programming?
2.1.
What Kind of Problems Does Dynamic Programming Solve?
3.
Is Dynamic Programming just Recursion?
4.
How does the dynamic programming approach work?
5.
Approaches of dynamic programming
6.
Ways to Solve Dynamic Programming Problems
6.1.
Fibonacci Number Series:
7.
Variations of Dynamic Programming Problems
7.1.
Stock Variation
7.2.
Expression Matching
7.3.
LCS and its variations
7.4.
0-1 Knapsack and its variations
8.
Frequently Asked Questions
9.
Conclusion
Last Updated: Aug 18, 2024

Getting Started with Dynamic Programming - Part 1

Author Ankit kumar
0 upvote

Introduction

A dynamic problem is an algorithm for solving harder and bigger problems by dividing them into smaller subproblems, keeping in mind that the optimal solution to bigger problems lies in smaller subproblems. We store the answer for the overlapping subproblems and use that result if we need the answer for the same problem in the future. The main idea is to avoid repetitive computations. The key components of dynamic programming are Recursion as well as Memoization. Hence,

Dynamic programming = recursion + memorization

What is Dynamic Programming?

Dynamic programming is a smart way of solving complex problems by breaking them down into smaller, more manageable subproblems. It's like divide and conquer but with a twist. Instead of solving each subproblem independently, dynamic programming remembers the solutions to these subproblems and reuses them when needed.


Think of it like building a puzzle. You start with the smallest pieces, solve them, and then gradually combine them to form the bigger picture. Dynamic programming follows a similar approach. It starts by solving the smallest subproblems and stores their results. Then, when it encounters a larger problem, it checks if it has already solved any of the smaller subproblems that make up the larger one. If it has, it simply reuses those solutions instead of solving them again.

What Kind of Problems Does Dynamic Programming Solve?

Dynamic Programming can solve problems that exhibit a specific structure where a problem can be broken down into smaller subproblems that are similar to the original problem. The very first and important step is to figure out that the problem can be solved using Dynamic Programming. After you figure it out, then there are two approaches for solving dynamic problems:

  1. Bottom-up dynamic programming: In this method, we begin with the smallest possible solution, which is known to us. After that, we find out the next values by utilizing the previously calculated values, which are, in this case, stored in a tabular structure.
  2. Top-down dynamic programming: In this method, the problem is simply broken down into smaller subproblems to the extent of the base case for which the return value is known. This value is then stored in order to use it for previous computation.

Is Dynamic Programming just Recursion?

Recursion is when a function can be called and executed by itself, while dynamic programming is the process of solving problems by breaking them down into sub-problems to resolve the complex one. Dynamic programming can function even without Recursion. Dynamic programming is the optimization technique that makes the previously calculated value in use in order to save time. In dynamic programming, a problem is broken into smaller subproblems, and that is what is called a Recursion.

How does the dynamic programming approach work?

 

The dynamic programming approach works in steps mentioned below:

1. Break down the problem: Breaking down the problem is the first step in dynamic programming. You take the big, complex problem and divide it into smaller, more manageable subproblems. Each subproblem is a simplified version of the original problem, focusing on a specific part or a smaller input size. By solving these subproblems, you gradually build up the solution to the main problem.

2. Identify overlapping subproblems: The next step is to identify overlapping subproblems. These are the subproblems that you encounter repeatedly while solving the main problem. Dynamic programming relies on the fact that many complex problems have overlapping subproblems. By recognizing these overlaps, you can avoid solving the same subproblems multiple times, which saves a lot of time and effort.

3. Solve subproblems and store results: Once you've identified the subproblems, you start solving them one by one. As you solve each subproblem, you store its result in a table or some other data structure. This table acts as a memory, allowing you to recall the solutions to subproblems whenever you need them in the future. By storing the results, you avoid redundant calculations and make the problem-solving process much more efficient.

4. Reuse stored results: As you progress towards solving the main problem, you'll encounter subproblems that you've already solved before. Instead of solving them again, you simply retrieve their results from the table where you stored them earlier. This is where the power of dynamic programming shines. By reusing previously computed results, you save a tremendous amount of time and computational resources.

5. Combine subproblem solutions: Finally, you combine the solutions of the subproblems to solve the main problem. This is like putting together the pieces of a puzzle. You take the results you stored from solving the subproblems and use them to build up the final answer. The combination process varies depending on the specific problem, but it typically involves some mathematical operations or logical reasoning.

Approaches of dynamic programming

Ways to Solve Dynamic Programming Problems

There are two different ways to store the values so that the values of a sub-problem can be reused. Both are discussed below :

  1. Tabulation or Bottom-up: Bottom-up is a technique that saves memory by avoiding Recursion, which has been incurred by recursion call stack. Bottom-up means starting from the beginning.
  2. Memoisation or Top-down: Memoisation assures that a function doesn't run again for the same inputs again and again by keeping a record of the results for the previously given inputs.

 

Let's look at an example to clearly understand the concept:

Fibonacci Number Series:

Recursive approach
 

int fibonacci(int n) {
    if (n <= 1)
        return n;

    int a = fibonacci(n - 1);
    int b = fibonacci(n - 2);

    return a + b;
}
You can also try this code with Online C++ Compiler
Run Code

 

Time-complexity : 2^n

 

Memoisation approach
 

int fib_helper(int n, int * ans) {
    if (n <= 1)
        Return n;

    if (ans[n] != -1)
        Return ans[n];

    Int a = fib_helper(n - 1, ans);
    Int b = fib_helper(n - 2, ans);

    Return ans[n] = a + b;
}
int fib(int n) {
    int * ans = new int[n + 1];
    for (int i = 0; i <= n; i++) {
        ans[i] = -1;
    }
    return fib_helper(n, ans);
}
You can also try this code with Online C++ Compiler
Run Code

 

Time-complexity : O(n)

 

Bottom-up approach
 

int fibo(int n) {
    int * ans = new int[n + 1];
    ans[0] = 1;
    ans[1] = 1;
    for (int i = 2; i <= n; i++) {
        ans[i] = ans[i - 1] + ans[i - 2];
    }
    return ans[n];
}
You can also try this code with Online C++ Compiler
Run Code

 

Time-complexity : O(n)

In depth discussion of the difference between tabulation is memoization is given here

Check out Longest Common Substring

Variations of Dynamic Programming Problems

There isn't any set of variations of problems in which a DP problem lies but frequently asked problems have a certain set of variations we will be discussing below:

Stock Variation

In this type of problem variation, we are generally asked to calculate the maximum profit one can make from the given daily trading chart by setting the number of times one can buy or sell the stock. Now ,clearly it is asking for an optimised result and we are given with choices to pick the stock to buy or sell, therefore it is a variation of dynamic programming problem. Refer to this for more details.

Expression Matching

In this type of problem variation, we are asked to match two strings by setting some wildcard rules for some characters. Here, we have the choice to choose from which index we use this wildcard. Therefore it is a Dynamic programming problem. Refer to this for more details.

LCS and its variations

In this variation type, we are given two strings and maybe asked to calculate the longest common substring or maybe given one string and asked to calculate the longest palindromic substring. Here ,we are asked for an optimised result and are given with choices whether to pick the element or not in the final result. Therefore, it is a variation of dynamic programming problem. Refer to this for more details.

0-1 Knapsack and its variations

In 0-1 knapsack problem and its variations, we are given with an array and asked to get the maximum profit while picking elements from the array by setting constrain on either the money or weight or any such entity. Since, we are asked to get an optimised result by picking or not picking elements from the array. Therefore it is a dynamic programming problem. Refer to this for more details.

Must Read Julia Programming Language

Frequently Asked Questions

What are the 4 dynamic programming languages?

Dynamic programming languages are those that execute many common programming behaviors at runtime that static programming languages perform during compilation. Four popular dynamic languages are Python, JavaScript, Ruby, and PHP. These languages are highly flexible, making them ideal for rapid application development and scripting.

How is Dynamic Programming different from normal programming?

Dynamic programming is not "programming" in that sense. It is not about writing code, but the word "programming" there is used in the context of solving complex problems by breaking them down into simpler problems.

How to solve a Dynamic Programming problem?

The first step is to identify the problem. The next step is to identify what type of variation it is, if possible. By doing so, it would be easy to solve the problem.

Conclusion

In this article, we discussed the concept of dynamic programming, discussed the types of problems it can solve effectively. We also compared dynamic programming with recursion to highlight their differences and when one might be more suitable than the other. Moreover, we looked at various problem scenarios where dynamic programming can be applied, which clearly shows why DP is very effective and effectiveness in solving complex computational problems. 

Refer to our guided paths on Coding Ninjas Studio to learn more about DSA, Competitive Programming, JavaScript, System Design, etc. Enroll in our courses and refer to the mock test and problems available, interview puzzles, take a look at the interview experiences, and interview bundle for placement preparations.

We hope that this blog has helped you enhance your knowledge regarding puzzles, and if you liked this blog, check other links.

Do upvote our blog to help other ninjas grow.

Happy Coding!"

Live masterclass