Showing posts with label Dynamic programming. Show all posts
Showing posts with label Dynamic programming. Show all posts

Monday, May 25, 2020

Peeling Concept of Dynamic Programming , Data-Structures and Algorithm

Peeling Concept of Dynamic Programming Data-Structures and Algorithm

Dynamic Programming(DP): Dp is a very simple technique but at the same time very difficult to master. The problem is how to identify and solve DP problems.

Another thing just keep in mind that DP and memorization(Means maintaining a table of subproblems already solved) work together. So what is the main difference between the 
Divide and Conquer and DP? Divide-Conquer,subproblems are independent whereas in DP the overlap of subproblems occur. This is the main difference.

So now why memoization? because it reduces the exponential complexity to polynomial complexity O(n2), O(n3) for many subproblems.

The major components of DP :

a)Recursion: Solves subproblems recursively.
b)Memorization: Stores already computed values in the table

Dynamic Programming = Recursion + Memorization

So how to identify that this problem will be solved by DP. Keep in mind.
a)Optimal substructure - So an optimal solution to a problem contains the given subproblems.
b)Overlapping subproblems- a recursive solution of subproblems.

So another question can we solve every problem using Dynamic programming?
The answer is no like greedy and divide and conquer not able to solve everything it is that same way. You have to understand one thing the difference between the DP and straightforward recursion is in the memorization of recursive calls.

If subproblems are independent and there is no repetition then memorization does not help so DP is not a solution to such problems.

Dynamic Programming Approaches

to solve any DP problem we have two approaches

1)Bottom-up dynamic programming
2)Top-down dynamic programming


Bottom-up Dynamic Programming : 

So here we start with smallest possible input argument value and then slowly increase input argument value and while doing this we store values in a table(memory).

Top-down Dynamic Programming:

So here we broke the problem in subproblems and these subproblems are solved and the solutions remembered in case they need to be solved. Also we save each computed value as a final action of a recursive function and at the same, we also check if pre-computed values exist.

Algorithms of Dynamic Programming : 

These are a few algorithms of DP.

1)String Algorithms include the longest common subsequence, longest increasing subsequence, longest common substring, edit distance.

2)Bellman-Ford Algorithm, Floyd's All pair shortest path algorithm.

3)Chain Matrix multiplication

4)Subset Sum

5)0/1 Knapsack

6)Travelling salesman problem 

Let's understand the Dynamic Programming in more depth:

Fibonacci Series(Current number is the sum of two previous number).Remember it.

Fib(n) = 0      for n =0
Fib(1) = 1      for n=1
           =  Fib(n-1) + Fib(n-2) ........ for n  > 1

So now think of its recursive solution which is very simple.

int RecursiveFibonacci(int n)
{
   if(n==0) return 0;
   if(n==1) return 1;

   return RecursiveFibonacci(n-1) + RecursiveFibonacci(n-2);
}

Above we discuss about Memorization So how Memorization helps here?
Ans: It helps like it produces a call tree that calls the function on the same value many times.

Fib(5) 
Fib(4) + Fib(3)
(Fib(3) + Fib(2))  + (Fib(2) + Fib(1))
...............

(((Fib(1) + Fib(0)) + Fib(1)) + (Fib(1) + Fib(0) + Fib(0))) + Fib(0) + Fib(1))

So here Fib(2) was calculated 3 times(overlapping of subproblems) this leads to an exponential time. Instead of solving the same subproblems again and again just keep track of it store the previously calculated values then it reduces the complexity. 

Bottom-up Approach:

int fib[n];
int fib(int n)
{
   if(n==0 || n==1)
   retun 1
   
   fib[0] =1;
   fib[1] =1;
   for(int i =2 ; i<n; i++)
   {
     fib[i] = fib[i -1] + fib[i-2]
   }
   
   return fib[n -1]
}

Top-down Approach :

int fib[n];
int fibonacci(int n)
{
   if(n==1) retun 1;
   if(n==2) retun 1;
   if(fib[n]!=0)
    {
  return fib[n];
}  
   return fib[n] = fibonacci(n -1) + fibonacci(n -2);
}

So both of them reduces the problem of complexity to O(n) this is because if a value is already computed then we are not calling the subproblems again. We are directly taking it from
table.

Time Complexity O(n) 
Space Complexity: O(n) for table.

We can further improve the space complexity by O(1)

So the question is How?
Ans: So just think about Fibonacci series is basically the current value is the sum of two previous calculations only. So we do not have to store all the previous values right? we just have two store last two values we can calculate the current value. 


















Tuesday, November 14, 2017

Dynamic Programming - Edit Distance


Question : Given two strings str1 and str2 and below operations that can performed on str1. Find minimum number of edits (operations) required to convert ‘str1’ into ‘str2’.

Example: 

Input:   str1 = "geek", str2 = "gesek"
Output:  1
We can convert str1 into str2 by inserting a 's'.

Input:   str1 = "cat", str2 = "cut"
Output:  1
We can convert str1 into str2 by replacing 'a' with 'u'.

Input:   str1 = "sunday", str2 = "saturday"
Output:  3
Last three and first characters are same.  We basically
need to convert "un" to "atur".  This can be done using
below three operations.
Replace 'n' with 'r', insert t, insert a


So there can be many many solution for this problem but giving you the best solution:

The idea is process all characters one by one staring from either from left or right sides of both strings.

Let we traverse from right corner, there are two possibilities for every pair of character being traversed.

m: Length of str1 (first string)
n: Length of str2 (second string)

If last characters of two strings are same, nothing much to do. Ignore last characters and get count for remaining strings. So we recur for lengths m-1 and n-1.

Else (If last characters are not same), we consider all operations on ‘str1’, consider all three operations on last character of first string, recursively compute minimum cost for all three operations and take minimum of three values.

Insert: Recur for m and n-1
Remove: Recur for m-1 and n
Replace: Recur for m-1 and n-1

Sample Program:

class EDISTTest
{
static int min(int x,int y,int z)
{
if (x<=y && x<=z) return x;
if (y<=x && y<=z) return y;
else return z;
}

static int editDist(String str1 , String str2 , int m ,int n)
{
if (m == 0) return n;

if (n == 0) return m;

if (str1.charAt(m-1) == str2.charAt(n-1))
return editDist(str1, str2, m-1, n-1);

return 1 + min ( editDist(str1, str2, m, n-1), // Insert
editDist(str1, str2, m-1, n), // Remove
editDist(str1, str2, m-1, n-1) // Replace
);
}

public static void main(String args[])
{
String str1 = "sunday";
String str2 = "saturday";

System.out.println( editDist( str1 , str2 , str1.length(), str2.length()) );
}
}

Output: 3

Time complexity:

The time complexity of above solution is exponential.
In worst case, we may end up doing O(3m) operations. The worst case happens when none of characters of two strings match.