0% found this document useful (0 votes)
789 views130 pages

DP Problems

The document contains code snippets and explanations for several dynamic programming problems related to longest increasing subsequence (LIS) variations. These include building bridges to connect matching pairs of cities across a river with no bridge crossings, finding the maximum sum increasing subsequence, and the word wrap problem of breaking a paragraph into lines to minimize cost. Dynamic programming solutions using arrays and memoization are presented to solve each problem in optimal O(n^2) time.

Uploaded by

lokenders801
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
789 views130 pages

DP Problems

The document contains code snippets and explanations for several dynamic programming problems related to longest increasing subsequence (LIS) variations. These include building bridges to connect matching pairs of cities across a river with no bridge crossings, finding the maximum sum increasing subsequence, and the word wrap problem of breaking a paragraph into lines to minimize cost. Dynamic programming solutions using arrays and memoization are presented to solve each problem in optimal O(n^2) time.

Uploaded by

lokenders801
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 130

// C/C++ program to find the length of the longest substring

// without repeating characters


#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#define NO_OF_CHARS 256

int min(int a, int b);

int longestUniqueSubsttr(char *str)


{
int n = strlen(str);
int cur_len = 1; // lenght of current substring
int max_len = 1; // result
int prev_index; // previous index
int i;
int *visited = (int *)malloc(sizeof(int)*NO_OF_CHARS);

/* Initialize the visited array as -1, -1 is used to


indicate that character has not been visited yet. */
for (i = 0; i < NO_OF_CHARS; i++)
visited[i] = -1;

/* Mark first character as visited by storing the index


of first character in visited array. */
visited[str[0]] = 0;

/* Start from the second character. First character is


already processed (cur_len and max_len are initialized
as 1, and visited[str[0]] is set */
for (i = 1; i < n; i++)
{
prev_index = visited[str[i]];

/* If the currentt character is not present in the


already processed substring or it is not part of
the current NRCS, then do cur_len++ */
if (prev_index == -1 || i - cur_len > prev_index)
cur_len++;

/* If the current character is present in currently


considered NRCS, then update NRCS to start from
the next character of previous instance. */
else
{
/* Also, when we are changing the NRCS, we
should also check whether length of the
previous NRCS was greater than max_len or
not.*/
if (cur_len > max_len)
max_len = cur_len;

cur_len = i - prev_index;
}

// update the index of current character


visited[str[i]] = i;
}

// Compare the length of last NRCS with max_len and


// update max_len if needed
if (cur_len > max_len)
max_len = cur_len;

free(visited); // free memory allocated for visited


return max_len;
}

/* A utility function to get the minimum of two integers */


int min(int a, int b)
{
return (a>b)?b:a;
}

/* Driver program to test above function */


int main()
{
char str[] = "ABDEFGABEF";
printf("The input string is %s \n", str);
int len = longestUniqueSubsttr(str);
printf("The length of the longest non-repeating "
"character substring is %d", len);
return 0;
}

// A Dynamic Programming based solution that uses table C[][] to


// calculate the Binomial Coefficient
#include<stdio.h>

// Prototype of a utility function that returns minimum of two integers


int min(int a, int b);

// Returns value of Binomial Coefficient C(n, k)


int binomialCoeff(int n, int k)
{
int C[n+1][k+1];
int i, j;

// Caculate value of Binomial Coefficient in bottom up manner


for (i = 0; i <= n; i++)
{
for (j = 0; j <= min(i, k); j++)
{
// Base Cases
if (j == 0 || j == i)
C[i][j] = 1;

// Calculate value using previosly stored values


else
C[i][j] = C[i-1][j-1] + C[i-1][j];
}
}

return C[n][k];
}

// A utility function to return minimum of two integers


int min(int a, int b)
{
return (a<b)? a: b;
}

/* Drier program to test above function*/


int main()
{
int n = 5, k = 2;
printf ("Value of C(%d, %d) is %d ", n, k, binomialCoeff(n, k) );
return 0;
}

/* Dynamic Programming implementation of Maximum Sum Increasing


Subsequence (MSIS) problem */
#include<stdio.h>

/* maxSumIS() returns the maximum sum of increasing subsequence


in arr[] of size n */
int maxSumIS( int arr[], int n )
{
int i, j, max = 0;
int msis[n];

/* Initialize msis values for all indexes */


for ( i = 0; i < n; i++ )
msis[i] = arr[i];

/* Compute maximum sum values in bottom up manner */


for ( i = 1; i < n; i++ )
for ( j = 0; j < i; j++ )
if ( arr[i] > arr[j] && msis[i] < msis[j] + arr[i])
msis[i] = msis[j] + arr[i];

/* Pick maximum of all msis values */


for ( i = 0; i < n; i++ )
if ( max < msis[i] )
max = msis[i];

return max;
}

/* Driver program to test above function */


int main()
{
int arr[] = {1, 101, 2, 3, 100, 4, 5};
int n = sizeof(arr)/sizeof(arr[0]);
printf("Sum of maximum sum increasing subsequence is %d\n",
maxSumIS( arr, n ) );
return 0;
}

// A recursive C program for partition problem


#include <stdio.h>

// A utility function that returns true if there is


// a subset of arr[] with sun equal to given sum
bool isSubsetSum (int arr[], int n, int sum)
{
// Base Cases
if (sum == 0)
return true;
if (n == 0 && sum != 0)
return false;

// If last element is greater than sum, then


// ignore it
if (arr[n-1] > sum)
return isSubsetSum (arr, n-1, sum);

/* else, check if sum can be obtained by any of


the following
(a) including the last element
(b) excluding the last element
*/
return isSubsetSum (arr, n-1, sum) ||
isSubsetSum (arr, n-1, sum-arr[n-1]);
}

// Returns true if arr[] can be partitioned in two


// subsets of equal sum, otherwise false
bool findPartiion (int arr[], int n)
{
// Calculate sum of the elements in array
int sum = 0;
for (int i = 0; i < n; i++)
sum += arr[i];

// If sum is odd, there cannot be two subsets


// with equal sum
if (sum%2 != 0)
return false;

// Find if there is subset with sum equal to


// half of total sum
return isSubsetSum (arr, n, sum/2);
}

// Driver program to test above function


int main()
{
int arr[] = {3, 1, 5, 9, 12};
int n = sizeof(arr)/sizeof(arr[0]);
if (findPartiion(arr, n) == true)
printf("Can be divided into two subsets "
"of equal sum");
else
printf("Can not be divided into two subsets"
" of equal sum");
return 0;
}

// A Dynamic programming solution for Word Wrap Problem


#include <limits.h>
#include <stdio.h>
#define INF INT_MAX

// A utility function to print the solution


int printSolution (int p[], int n);

// l[] represents lengths of different words in input sequence. For example,


// l[] = {3, 2, 2, 5} is for a sentence like "aaa bb cc ddddd". n is size of
// l[] and M is line width (maximum no. of characters that can fit in a line)
void solveWordWrap (int l[], int n, int M)
{
// For simplicity, 1 extra space is used in all below arrays

// extras[i][j] will have number of extra spaces if words from i


// to j are put in a single line
int extras[n+1][n+1];

// lc[i][j] will have cost of a line which has words from


// i to j
int lc[n+1][n+1];

// c[i] will have total cost of optimal arrangement of words


// from 1 to i
int c[n+1];

// p[] is used to print the solution.


int p[n+1];

int i, j;

// calculate extra spaces in a single line. The value extra[i][j]


// indicates extra spaces if words from word number i to j are
// placed in a single line
for (i = 1; i <= n; i++)
{
extras[i][i] = M - l[i-1];
for (j = i+1; j <= n; j++)
extras[i][j] = extras[i][j-1] - l[j-1] - 1;
}

// Calculate line cost corresponding to the above calculated extra


// spaces. The value lc[i][j] indicates cost of putting words from
// word number i to j in a single line
for (i = 1; i <= n; i++)
{
for (j = i; j <= n; j++)
{
if (extras[i][j] < 0)
lc[i][j] = INF;
else if (j == n && extras[i][j] >= 0)
lc[i][j] = 0;
else
lc[i][j] = extras[i][j]*extras[i][j];
}
}

// Calculate minimum cost and find minimum cost arrangement.


// The value c[j] indicates optimized cost to arrange words
// from word number 1 to j.
c[0] = 0;
for (j = 1; j <= n; j++)
{
c[j] = INF;
for (i = 1; i <= j; i++)
{
if (c[i-1] != INF && lc[i][j] != INF && (c[i-1] + lc[i][j] <
c[j]))
{
c[j] = c[i-1] + lc[i][j];
p[j] = i;
}
}
}

printSolution(p, n);
}

int printSolution (int p[], int n)


{
int k;
if (p[n] == 1)
k = 1;
else
k = printSolution (p, p[n]-1) + 1;
printf ("Line number %d: From word no. %d to %d \n", k, p[n], n);
return k;
}

// Driver program to test above functions


int main()
{
int l[] = {3, 2, 2, 5};
int n = sizeof(l)/sizeof(l[0]);
int M = 6;
solveWordWrap (l, n, M);
return 0;
}
Dynamic Programming | Set 21 (Variations of LIS)
We have discussed Dynamic Programming solution for Longest Increasing Subsequence problem
in this post and a O(nLogn) solution in this post. Following are commonly asked variations of the
standard LIS problem.
1. Building Bridges: Consider a 2-D map with a horizontal river passing through its center. There are n
cities on the southern bank with x-coordinates a(1) a(n) and n cities on the northern bank with x-
coordinates b(1) b(n). You want to connect as many north-south pairs of cities as possible with bridges
such that no two bridges cross. When connecting cities, you can only connect city i on the northern bank
to city i on the southern bank.
8 1 4 3 5 2 6 7

<---- Cities on the other bank of river---->

--------------------------------------------

<--------------- River--------------->

--------------------------------------------

1 2 3 4 5 6 7 8

<------- Cities on one bank of river------->

Source: Dynamic Programming Practice Problems. The link also has well explained solution for the
problem.

2. Maximum Sum Increasing Subsequence: Given an array of n positive integers. Write a program to
find the maximum sum subsequence of the given array such that the intgers in the subsequence are
sorted in increasing order. For example, if input is {1, 101, 2, 3, 100, 4, 5}, then output should be {1, 2, 3,
100}. The solution to this problem has been published here.

3. The Longest Chain You are given pairs of numbers. In a pair, the first number is smaller with respect
to the second number. Suppose you have two sets (a, b) and (c, d), the second set can follow the first set
if b < c. So you can form a long chain in the similar fashion. Find the longest chain which can be formed.
The solution to this problem has been published here.

4. Box Stacking You are given a set of n types of rectangular 3-D boxes, where the i^th box has height
h(i), width w(i) and depth d(i) (all real numbers). You want to create a stack of boxes which is as tall as
possible, but you can only stack a box on top of another box if the dimensions of the 2-D base of the
lower box are each strictly larger than those of the 2-D base of the higher box. Of course, you can rotate
a box so that any side functions as its base. It is also allowable to use multiple instances of the same type
of box.
// A dynamic programming solution for longest palindr.
// This code is adopted from following link
// http://www.leetcode.com/2011/11/longest-palindromic-substring-part-i.html

#include <stdio.h>
#include <string.h>

// A utility function to print a substring str[low..high]


void printSubStr( char* str, int low, int high )
{
for( int i = low; i <= high; ++i )
printf("%c", str[i]);
}

// This function prints the longest palindrome substring


// of str[].
// It also returns the length of the longest palindrome
int longestPalSubstr( char *str )
{
int n = strlen( str ); // get length of input string

// table[i][j] will be false if substring str[i..j]


// is not palindrome.
// Else table[i][j] will be true
bool table[n][n];
memset(table, 0, sizeof(table));

// All substrings of length 1 are palindromes


int maxLength = 1;
for (int i = 0; i < n; ++i)
table[i][i] = true;

// check for sub-string of length 2.


int start = 0;
for (int i = 0; i < n-1; ++i)
{
if (str[i] == str[i+1])
{
table[i][i+1] = true;
start = i;
maxLength = 2;
}
}

// Check for lengths greater than 2. k is length


// of substring
for (int k = 3; k <= n; ++k)
{
// Fix the starting index
for (int i = 0; i < n-k+1 ; ++i)
{
// Get the ending index of substring from
// starting index i and length k
int j = i + k - 1;

// checking for sub-string from ith index to


// jth index iff str[i+1] to str[j-1] is a
// palindrome
if (table[i+1][j-1] && str[i] == str[j])
{
table[i][j] = true;

if (k > maxLength)
{
start = i;
maxLength = k;
}
}
}
}

printf("Longest palindrome substring is: ");


printSubStr( str, start, start + maxLength - 1 );

return maxLength; // return length of LPS


}

// Driver program to test above functions


int main()
{
char str[] = "forgeeksskeegfor";
printf("\nLength is: %d\n", longestPalSubstr( str ) );
return 0;
}

/* Dynamic programming based program for Largest Independent Set problem */


#include <stdio.h>
#include <stdlib.h>

// A utility function to find max of two integers


int max(int x, int y) { return (x > y)? x: y; }

/* A binary tree node has data, pointer to left child and a pointer to
right child */
struct node
{
int data;
int liss;
struct node *left, *right;
};

// A memoization function returns size of the largest independent set in


// a given binary tree
int LISS(struct node *root)
{
if (root == NULL)
return 0;

if (root->liss)
return root->liss;

if (root->left == NULL && root->right == NULL)


return (root->liss = 1);

// Calculate size excluding the current node


int liss_excl = LISS(root->left) + LISS(root->right);

// Calculate size including the current node


int liss_incl = 1;
if (root->left)
liss_incl += LISS(root->left->left) + LISS(root->left->right);
if (root->right)
liss_incl += LISS(root->right->left) + LISS(root->right->right);

// Maximum of two sizes is LISS, store it for future uses.


root->liss = max(liss_incl, liss_excl);

return root->liss;
}

// A utility function to create a node


struct node* newNode(int data)
{
struct node* temp = (struct node *) malloc( sizeof(struct node) );
temp->data = data;
temp->left = temp->right = NULL;
temp->liss = 0;
return temp;
}

// Driver program to test above functions


int main()
{
// Let us construct the tree given in the above diagram
struct node *root = newNode(20);
root->left = newNode(8);
root->left->left = newNode(4);
root->left->right = newNode(12);
root->left->right->left = newNode(10);
root->left->right->right = newNode(14);
root->right = newNode(22);
root->right->right = newNode(25);

printf ("Size of the Largest Independent Set is %d ", LISS(root));

return 0;
}

// A Dynamic Programming based program to find minimum number


// insertions needed to make a string palindrome
#include <stdio.h>
#include <string.h>
// A utility function to find minimum of two integers
int min(int a, int b)
{ return a < b ? a : b; }

// A DP function to find minimum number of insersions


int findMinInsertionsDP(char str[], int n)
{
// Create a table of size n*n. table[i][j] will store
// minumum number of insertions needed to convert str[i..j]
// to a palindrome.
int table[n][n], l, h, gap;

// Initialize all table entries as 0


memset(table, 0, sizeof(table));

// Fill the table


for (gap = 1; gap < n; ++gap)
for (l = 0, h = gap; h < n; ++l, ++h)
table[l][h] = (str[l] == str[h])? table[l+1][h-1] :
(min(table[l][h-1], table[l+1][h]) + 1);

// Return minimum number of insertions for str[0..n-1]


return table[0][n-1];
}

// Driver program to test above function.


int main()
{
char str[] = "geeks";
printf("%d", findMinInsertionsDP(str, strlen(str)));
return 0;
}

// C program to find out maximum value from a given sequence of coins


#include <stdio.h>
#include <limits.h>

// Utility functions to get maximum and minimum of two intgers


int max(int a, int b) { return a > b ? a : b; }
int min(int a, int b) { return a < b ? a : b; }

// Returns optimal value possible that a player can collect from


// an array of coins of size n. Note than n must be even
int optimalStrategyOfGame(int* arr, int n)
{
// Create a table to store solutions of subproblems
int table[n][n], gap, i, j, x, y, z;

// Fill table using above recursive formula. Note that the table
// is filled in diagonal fashion (similar to http://goo.gl/PQqoS),
// from diagonal elements to table[0][n-1] which is the result.
for (gap = 0; gap < n; ++gap)
{
for (i = 0, j = gap; j < n; ++i, ++j)
{
// Here x is value of F(i+2, j), y is F(i+1, j-1) and
// z is F(i, j-2) in above recursive formula
x = ((i+2) <= j) ? table[i+2][j] : 0;
y = ((i+1) <= (j-1)) ? table[i+1][j-1] : 0;
z = (i <= (j-2))? table[i][j-2]: 0;

table[i][j] = max(arr[i] + min(x, y), arr[j] + min(y, z));


}
}

return table[0][n-1];
}

// Driver program to test above function


int main()
{
int arr1[] = {8, 15, 3, 7};
int n = sizeof(arr1)/sizeof(arr1[0]);
printf("%d\n", optimalStrategyOfGame(arr1, n));

int arr2[] = {2, 2, 2, 2};


n = sizeof(arr2)/sizeof(arr2[0]);
printf("%d\n", optimalStrategyOfGame(arr2, n));

int arr3[] = {20, 30, 2, 2, 2, 10};


n = sizeof(arr3)/sizeof(arr3[0]);
printf("%d\n", optimalStrategyOfGame(arr3, n));

return 0;
}

// A Dynamic Programming based program to test whether a given string can


// be segmented into space separated words in dictionary
#include <iostream>
#include <string.h>
using namespace std;

/* A utility function to check whether a word is present in dictionary or


not.
An array of strings is used for dictionary. Using array of strings for
dictionary is definitely not a good idea. We have used for simplicity of
the program*/
int dictionaryContains(string word)
{
string dictionary[] = {"mobile","samsung","sam","sung","man","mango",
"icecream","and","go","i","like","ice","cream"};
int size = sizeof(dictionary)/sizeof(dictionary[0]);
for (int i = 0; i < size; i++)
if (dictionary[i].compare(word) == 0)
return true;
return false;
}

// Returns true if string can be segmented into space separated


// words, otherwise returns false
bool wordBreak(string str)
{
int size = str.size();
if (size == 0) return true;

// Create the DP table to store results of subroblems. The value wb[i]


// will be true if str[0..i-1] can be segmented into dictionary words,
// otherwise false.
bool wb[size+1];
memset(wb, 0, sizeof(wb)); // Initialize all values as false.

for (int i=1; i<=size; i++)


{
// if wb[i] is false, then check if current prefix can make it true.
// Current prefix is "str.substr(0, i)"
if (wb[i] == false && dictionaryContains( str.substr(0, i) ))
wb[i] = true;

// wb[i] is true, then check for all substrings starting from


// (i+1)th character and store their results.
if (wb[i] == true)
{
// If we reached the last prefix
if (i == size)
return true;

for (int j = i+1; j <= size; j++)


{
// Update wb[j] if it is false and can be updated
// Note the parameter passed to dictionaryContains() is
// substring starting from index 'i' and length 'j-i'
if (wb[j] == false && dictionaryContains( str.substr(i, j-i)
))
wb[j] = true;

// If we reached the last character


if (j == size && wb[j] == true)
return true;
}
}
}

/* Uncomment these lines to print DP table "wb[]"


for (int i = 1; i <= size; i++)
cout << " " << wb[i]; */

// If we have tried all prefixes and none of them worked


return false;
}

// Driver program to test above functions


int main()
{
wordBreak("ilikesamsung")? cout <<"Yes\n": cout << "No\n";
wordBreak("iiiiiiii")? cout <<"Yes\n": cout << "No\n";
wordBreak("")? cout <<"Yes\n": cout << "No\n";
wordBreak("ilikelikeimangoiii")? cout <<"Yes\n": cout << "No\n";
wordBreak("samsungandmango")? cout <<"Yes\n": cout << "No\n";
wordBreak("samsungandmangok")? cout <<"Yes\n": cout << "No\n";
return 0;
}

// A C program to find minimum possible time by the car chassis to complete


#include <stdio.h>
#define NUM_LINE 2
#define NUM_STATION 4

// Utility function to find minimum of two numbers


int min(int a, int b) { return a < b ? a : b; }

int carAssembly(int a[][NUM_STATION], int t[][NUM_STATION], int *e, int *x)


{
int T1[NUM_STATION], T2[NUM_STATION], i;

T1[0] = e[0] + a[0][0]; // time taken to leave first station in line 1


T2[0] = e[1] + a[1][0]; // time taken to leave first station in line 2

// Fill tables T1[] and T2[] using the above given recursive relations
for (i = 1; i < NUM_STATION; ++i)
{
T1[i] = min(T1[i-1] + a[0][i], T2[i-1] + t[1][i] + a[0][i]);
T2[i] = min(T2[i-1] + a[1][i], T1[i-1] + t[0][i] + a[1][i]);
}

// Consider exit times and retutn minimum


return min(T1[NUM_STATION-1] + x[0], T2[NUM_STATION-1] + x[1]);
}

int main()
{
int a[][NUM_STATION] = {{4, 5, 3, 2},
{2, 10, 1, 4}};
int t[][NUM_STATION] = {{0, 7, 4, 5},
{0, 9, 2, 8}};
int e[] = {10, 12}, x[] = {18, 7};

printf("%d", carAssembly(a, t, e, x));

return 0;
}
// C++ program to find Length of the Longest AP (llap) in a given sorted set.
// The code strictly implements the algorithm provided in the reference.
#include <iostream>
using namespace std;

// Returns length of the longest AP subset in a given set


int lenghtOfLongestAP(int set[], int n)
{
if (n <= 2) return n;

// Create a table and initialize all values as 2. The value of


// L[i][j] stores LLAP with set[i] and set[j] as first two
// elements of AP. Only valid entries are the entries where j>i
int L[n][n];
int llap = 2; // Initialize the result

// Fill entries in last column as 2. There will always be


// two elements in AP with last number of set as second
// element in AP
for (int i = 0; i < n; i++)
L[i][n-1] = 2;

// Consider every element as second element of AP


for (int j=n-2; j>=1; j--)
{
// Search for i and k for j
int i = j-1, k = j+1;
while (i >= 0 && k <= n-1)
{
if (set[i] + set[k] < 2*set[j])
k++;

// Before changing i, set L[i][j] as 2


else if (set[i] + set[k] > 2*set[j])
{ L[i][j] = 2, i--; }

else
{
// Found i and k for j, LLAP with i and j as first two
// elements is equal to LLAP with j and k as first two
// elements plus 1. L[j][k] must have been filled
// before as we run the loop from right side
L[i][j] = L[j][k] + 1;

// Update overall LLAP, if needed


llap = max(llap, L[i][j]);

// Change i and k to fill more L[i][j] values for


// current j
i--; k++;
}
}

// If the loop was stopped due to k becoming more than


// n-1, set the remaining entties in column j as 2
while (i >= 0)
{
L[i][j] = 2;
i--;
}
}
return llap;
}

/* Drier program to test above function*/


int main()
{
int set1[] = {1, 7, 10, 13, 14, 19};
int n1 = sizeof(set1)/sizeof(set1[0]);
cout << lenghtOfLongestAP(set1, n1) << endl;

int set2[] = {1, 7, 10, 15, 27, 29};


int n2 = sizeof(set2)/sizeof(set2[0]);
cout << lenghtOfLongestAP(set2, n2) << endl;

int set3[] = {2, 4, 6, 8, 10};


int n3 = sizeof(set3)/sizeof(set3[0]);
cout << lenghtOfLongestAP(set3, n3) << endl;

return 0;
}

// C++ program to count walks from u to v with exactly k edges


#include <iostream>
using namespace std;

// Number of vertices in the graph


#define V 4

// A Dynamic programming based function to count walks from u


// to v with k edges
int countwalks(int graph[][V], int u, int v, int k)
{
// Table to be filled up using DP. The value count[i][j][e] will
// store count of possible walks from i to j with exactly k edges
int count[V][V][k+1];

// Loop for number of edges from 0 to k


for (int e = 0; e <= k; e++)
{
for (int i = 0; i < V; i++) // for source
{
for (int j = 0; j < V; j++) // for destination
{
// initialize value
count[i][j][e] = 0;

// from base cases


if (e == 0 && i == j)
count[i][j][e] = 1;
if (e == 1 && graph[i][j])
count[i][j][e] = 1;

// go to adjacent only when number of edges is more than 1


if (e > 1)
{
for (int a = 0; a < V; a++) // adjacent of source i
if (graph[i][a])
count[i][j][e] += count[a][j][e-1];
}
}
}
}
return count[u][v][k];
}

// driver program to test above function


int main()
{
/* Let us create the graph shown in above diagram*/
int graph[V][V] = { {0, 1, 1, 1},
{0, 0, 0, 1},
{0, 0, 0, 1},
{0, 0, 0, 0}
};
int u = 0, v = 3, k = 2;
cout << countwalks(graph, u, v, k);
return 0;
}

// Dynamic Programming based C++ program to find shortest path with


// exactly k edges
#include <iostream>
#include <climits>
using namespace std;

// Define number of vertices in the graph and inifinite value


#define V 4
#define INF INT_MAX

// A Dynamic programming based function to find the shortest path from


// u to v with exactly k edges.
int shortestPath(int graph[][V], int u, int v, int k)
{
// Table to be filled up using DP. The value sp[i][j][e] will store
// weight of the shortest path from i to j with exactly k edges
int sp[V][V][k+1];

// Loop for number of edges from 0 to k


for (int e = 0; e <= k; e++)
{
for (int i = 0; i < V; i++) // for source
{
for (int j = 0; j < V; j++) // for destination
{
// initialize value
sp[i][j][e] = INF;

// from base cases


if (e == 0 && i == j)
sp[i][j][e] = 0;
if (e == 1 && graph[i][j] != INF)
sp[i][j][e] = graph[i][j];

//go to adjacent only when number of edges is more than 1


if (e > 1)
{
for (int a = 0; a < V; a++)
{
// There should be an edge from i to a and a
// should not be same as either i or j
if (graph[i][a] != INF && i != a &&
j!= a && sp[a][j][e-1] != INF)
sp[i][j][e] = min(sp[i][j][e], graph[i][a] +
sp[a][j][e-1]);
}
}
}
}
}
return sp[u][v][k];
}

// driver program to test above function


int main()
{
/* Let us create the graph shown in above diagram*/
int graph[V][V] = { {0, 10, 3, 2},
{INF, 0, INF, 7},
{INF, INF, 0, 6},
{INF, INF, INF, 0}
};
int u = 0, v = 3, k = 2;
cout << shortestPath(graph, u, v, k);
return 0;
}

// A Dynamic Programming based C program to count number of


// possible numbers of given length
#include <stdio.h>

// Return count of all possible numbers of length n


// in a given numeric keyboard
int getCount(char keypad[][3], int n)
{
if(keypad == NULL || n <= 0)
return 0;
if(n == 1)
return 10;
// left, up, right, down move from current location
int row[] = {0, 0, -1, 0, 1};
int col[] = {0, -1, 0, 1, 0};

// taking n+1 for simplicity - count[i][j] will store


// number count starting with digit i and length j
int count[10][n+1];
int i=0, j=0, k=0, move=0, ro=0, co=0, num = 0;
int nextNum=0, totalCount = 0;

// count numbers starting with digit i and of lengths 0 and 1


for (i=0; i<=9; i++)
{
count[i][0] = 0;
count[i][1] = 1;
}

// Bottom up - Get number count of length 2, 3, 4, ... , n


for (k=2; k<=n; k++)
{
for (i=0; i<4; i++) // Loop on keypad row
{
for (j=0; j<3; j++) // Loop on keypad column
{
// Process for 0 to 9 digits
if (keypad[i][j] != '*' && keypad[i][j] != '#')
{
// Here we are counting the numbers starting with
// digit keypad[i][j] and of length k keypad[i][j]
// will become 1st digit, and we need to look for
// (k-1) more digits
num = keypad[i][j] - '0';
count[num][k] = 0;

// move left, up, right, down from current location


// and if new location is valid, then get number
// count of length (k-1) from that new digit and
// add in count we found so far
for (move=0; move<5; move++)
{
ro = i + row[move];
co = j + col[move];
if (ro >= 0 && ro <= 3 && co >=0 && co <= 2 &&
keypad[ro][co] != '*' && keypad[ro][co] != '#')
{
nextNum = keypad[ro][co] - '0';
count[num][k] += count[nextNum][k-1];
}
}
}
}
}
}

// Get count of all possible numbers of length "n" starting


// with digit 0, 1, 2, ..., 9
totalCount = 0;
for (i=0; i<=9; i++)
totalCount += count[i][n];
return totalCount;
}

// Driver program to test above function


int main(int argc, char *argv[])
{
char keypad[4][3] = {{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}};
printf("Count for numbers of length %d: %d\n", 1, getCount(keypad, 1));
printf("Count for numbers of length %d: %d\n", 2, getCount(keypad, 2));
printf("Count for numbers of length %d: %d\n", 3, getCount(keypad, 3));
printf("Count for numbers of length %d: %d\n", 4, getCount(keypad, 4));
printf("Count for numbers of length %d: %d\n", 5, getCount(keypad, 5));

return 0;
}

// A Dynamic Programming based program to find minimum cost of convex


// polygon triangulation
#include <iostream>
#include <cmath>
#define MAX 1000000.0
using namespace std;

// Structure of a point in 2D plane


struct Point
{
int x, y;
};

// Utility function to find minimum of two double values


double min(double x, double y)
{
return (x <= y)? x : y;
}

// A utility function to find distance between two points in a plane


double dist(Point p1, Point p2)
{
return sqrt((p1.x - p2.x)*(p1.x - p2.x) +
(p1.y - p2.y)*(p1.y - p2.y));
}

// A utility function to find cost of a triangle. The cost is considered


// as perimeter (sum of lengths of all edges) of the triangle
double cost(Point points[], int i, int j, int k)
{
Point p1 = points[i], p2 = points[j], p3 = points[k];
return dist(p1, p2) + dist(p2, p3) + dist(p3, p1);
}

// A Dynamic programming based function to find minimum cost for convex


// polygon triangulation.
double mTCDP(Point points[], int n)
{
// There must be at least 3 points to form a triangle
if (n < 3)
return 0;

// table to store results of subproblems. table[i][j] stores cost of


// triangulation of points from i to j. The entry table[0][n-1] stores
// the final result.
double table[n][n];

// Fill table using above recursive formula. Note that the table
// is filled in diagonal fashion i.e., from diagonal elements to
// table[0][n-1] which is the result.
for (int gap = 0; gap < n; gap++)
{
for (int i = 0, j = gap; j < n; i++, j++)
{
if (j < i+2)
table[i][j] = 0.0;
else
{
table[i][j] = MAX;
for (int k = i+1; k < j; k++)
{
double val = table[i][k] + table[k][j] + cost(points,i,j,k);
if (table[i][j] > val)
table[i][j] = val;
}
}
}
}
return table[0][n-1];
}

// Driver program to test above functions


int main()
{
Point points[] = {{0, 0}, {1, 0}, {2, 1}, {1, 2}, {0, 2}};
int n = sizeof(points)/sizeof(points[0]);
cout << mTCDP(points, n);
return 0;
}

/* Dynamic programming based program for Vertex Cover problem for


a Binary Tree */
#include <stdio.h>
#include <stdlib.h>
// A utility function to find min of two integers
int min(int x, int y) { return (x < y)? x: y; }

/* A binary tree node has data, pointer to left child and a pointer to
right child */
struct node
{
int data;
int vc;
struct node *left, *right;
};

// A memoization based function that returns size of the minimum vertex


cover.
int vCover(struct node *root)
{
// The size of minimum vertex cover is zero if tree is empty or there
// is only one node
if (root == NULL)
return 0;
if (root->left == NULL && root->right == NULL)
return 0;

// If vertex cover for this node is already evaluated, then return it


// to save recomputation of same subproblem again.
if (root->vc != 0)
return root->vc;

// Calculate size of vertex cover when root is part of it


int size_incl = 1 + vCover(root->left) + vCover(root->right);

// Calculate size of vertex cover when root is not part of it


int size_excl = 0;
if (root->left)
size_excl += 1 + vCover(root->left->left) + vCover(root->left->right);
if (root->right)
size_excl += 1 + vCover(root->right->left) + vCover(root->right-
>right);

// Minimum of two values is vertex cover, store it before returning


root->vc = min(size_incl, size_excl);

return root->vc;
}

// A utility function to create a node


struct node* newNode( int data )
{
struct node* temp = (struct node *) malloc( sizeof(struct node) );
temp->data = data;
temp->left = temp->right = NULL;
temp->vc = 0; // Set the vertex cover as 0
return temp;
}

// Driver program to test above functions


int main()
{
// Let us construct the tree given in the above diagram
struct node *root = newNode(20);
root->left = newNode(8);
root->left->left = newNode(4);
root->left->right = newNode(12);
root->left->right->left = newNode(10);
root->left->right->right = newNode(14);
root->right = newNode(22);
root->right->right = newNode(25);

printf ("Size of the smallest vertex cover is %d ", vCover(root));

return 0;
}

/* A Dynamic Programming based C program to find maximum number of A's


that can be printed using four keys */
#include<stdio.h>

// this function returns the optimal length string for N keystrokes


int findoptimal(int N)
{
// The optimal string length is N when N is smaller than 7
if (N <= 6)
return N;

// An array to store result of subproblems


int screen[N];

int b; // To pick a breakpoint

// Initializing the optimal lengths array for uptil 6 input


// strokes.
int n;
for (n=1; n<=6; n++)
screen[n-1] = n;

// Solve all subproblems in bottom manner


for (n=7; n<=N; n++)
{
// Initialize length of optimal string for n keystrokes
screen[n-1] = 0;

// For any keystroke n, we need to loop from n-3 keystrokes


// back to 1 keystroke to find a breakpoint 'b' after which we
// will have ctrl-a, ctrl-c and then only ctrl-v all the way.
for (b=n-3; b>=1; b--)
{
// if the breakpoint is at b'th keystroke then
// the optimal string would have length
// (n-b-1)*screen[b-1];
int curr = (n-b-1)*screen[b-1];
if (curr > screen[n-1])
screen[n-1] = curr;
}
}

return screen[N-1];
}

// Driver program
int main()
{
int N;

// for the rest of the array we will rely on the previous


// entries to compute new ones
for (N=1; N<=20; N++)
printf("Maximum Number of A's with %d keystrokes is %d\n",
N, findoptimal(N));
}

// C++ program to count all possible way to construct buildings


#include<iostream>
using namespace std;

// Returns count of possible ways for N sections


int countWays(int N)
{
// Base case
if (N == 1)
return 4; // 2 for one side and 4 for two sides

// countB is count of ways with a building at the end


// countS is count of ways with a space at the end
// prev_countB and prev_countS are previous values of
// countB and countS respectively.

// Initialize countB and countS for one side


int countB=1, countS=1, prev_countB, prev_countS;

// Use the above recursive formula for calculating


// countB and countS using previous values
for (int i=2; i<=N; i++)
{
prev_countB = countB;
prev_countS = countS;

countS = prev_countB + prev_countS;


countB = prev_countS;
}

// Result for one side is sum of ways ending with building


// and ending with space
int result = countS + countB;
// Result for 2 sides is square of result for one side
return (result*result);
}

// Driver program
int main()
{
int N = 3;
cout << "Count of ways for " << N
<< " sections is " << countWays(N);
return 0;
}

/* A dynamic programming based C program to find length


of the shortest supersequence */
#include<bits/stdc++.h>
using namespace std;

// Returns length of the shortest supersequence of X and Y


int superSeq(char* X, char* Y, int m, int n)
{
int dp[m+1][n+1];

// Fill table in bottom up manner


for (int i = 0; i <= m; i++)
{
for (int j = 0; j <= n; j++)
{
// Below steps follow above recurrence
if (!i)
dp[i][j] = j;
else if (!j)
dp[i][j] = i;
else if (X[i-1] == Y[j-1])
dp[i][j] = 1 + dp[i-1][j-1];
else
dp[i][j] = 1 + min(dp[i-1][j], dp[i][j-1]);
}
}

return dp[m][n];
}

// Driver program to test above function


int main()
{
char X[] = "AGGTAB";
char Y[] = "GXTXAYB";
cout << "Length of the shortest supersequence is "
<< superSeq(X, Y, strlen(X), strlen(Y));
return 0;
}
// C++ program to find the longest consecutive path
#include<bits/stdc++.h>
#define R 3
#define C 3
using namespace std;

// tool matrices to recur for adjacent cells.


int x[] = {0, 1, 1, -1, 1, 0, -1, -1};
int y[] = {1, 0, 1, 1, -1, -1, 0, -1};

// dp[i][j] Stores length of longest consecutive path


// starting at arr[i][j].
int dp[R][C];

// check whether mat[i][j] is a valid cell or not.


bool isvalid(int i, int j)
{
if (i < 0 || j < 0 || i >= R || j >= C)
return false;
return true;
}

// Check whether current character is adjacent to previous


// character (character processed in parent call) or not.
bool isadjacent(char prev, char curr)
{
return ((curr - prev) == 1);
}

// i, j are the indices of the current cell and prev is the


// character processed in the parent call.. also mat[i][j]
// is our current character.
int getLenUtil(char mat[R][C], int i, int j, char prev)
{
// If this cell is not valid or current character is not
// adjacent to previous one (e.g. d is not adjacent to b )
// or if this cell is already included in the path than return 0.
if (!isvalid(i, j) || !isadjacent(prev, mat[i][j]))
return 0;

// If this subproblem is already solved , return the answer


if (dp[i][j] != -1)
return dp[i][j];

int ans = 0; // Initialize answer

// recur for paths with differnt adjacent cells and store


// the length of longest path.
for (int k=0; k<8; k++)
ans = max(ans, 1 + getLenUtil(mat, i + x[k],
j + y[k], mat[i][j]));

// save the answer and return


return dp[i][j] = ans;
}

// Returns length of the longest path with all characters consecutive


// to each other. This function first initializes dp array that
// is used to store results of subproblems, then it calls
// recursive DFS based function getLenUtil() to find max length path
int getLen(char mat[R][C], char s)
{
memset(dp, -1, sizeof dp);
int ans = 0;

for (int i=0; i<R; i++)


{
for (int j=0; j<C; j++)
{
// check for each possible starting point
if (mat[i][j] == s) {

// recur for all eight adjacent cells


for (int k=0; k<8; k++)
ans = max(ans, 1 + getLenUtil(mat,
i + x[k], j + y[k], s));
}
}
}
return ans;
}

// Driver program
int main() {

char mat[R][C] = { {'a','c','d'},


{ 'h','b','a'},
{ 'i','g','f'}};

cout << getLen(mat, 'a') << endl;


cout << getLen(mat, 'e') << endl;
cout << getLen(mat, 'b') << endl;
cout << getLen(mat, 'f') << endl;
return 0;
}

// C++ program to find minimum initial points to reach destination


#include<bits/stdc++.h>
#define R 3
#define C 3
using namespace std;

int minInitialPoints(int points[][C])


{
// dp[i][j] represents the minimum initial points player
// should have so that when starts with cell(i, j) successfully
// reaches the destination cell(m-1, n-1)
int dp[R][C];
int m = R, n = C;

// Base case
dp[m-1][n-1] = points[m-1][n-1] > 0? 1:
abs(points[m-1][n-1]) + 1;
// Fill last row and last column as base to fill
// entire table
for (int i = m-2; i >= 0; i--)
dp[i][n-1] = max(dp[i+1][n-1] - points[i][n-1], 1);
for (int j = n-2; j >= 0; j--)
dp[m-1][j] = max(dp[m-1][j+1] - points[m-1][j], 1);

// fill the table in bottom-up fashion


for (int i=m-2; i>=0; i--)
{
for (int j=n-2; j>=0; j--)
{
int min_points_on_exit = min(dp[i+1][j], dp[i][j+1]);
dp[i][j] = max(min_points_on_exit - points[i][j], 1);
}
}

return dp[0][0];
}

// Driver Program
int main()
{

int points[R][C] = { {-2,-3,3},


{-5,-10,1},
{10,30,-5}
};
cout << "Minimum Initial Points Required: "
<< minInitialPoints(points);
return 0;
}

// A memoization based recursive program to count


// numbers with sum of n as given 'sum'
#include<bits/stdc++.h>
using namespace std;

// A lookup table used for memoization


unsigned long long int lookup[101][50001];

// Memoizatiob based implementation of recursive


// function
unsigned long long int countRec(int n, int sum)
{
// Base case
if (n == 0)
return sum == 0;

// If this subproblem is already evaluated,


// return the evaluated value
if (lookup[n][sum] != -1)
return lookup[n][sum];

// Initialize answer
unsigned long long int ans = 0;

// Traverse through every digit and


// recursively count numbers beginning
// with it
for (int i=0; i<10; i++)
if (sum-i >= 0)
ans += countRec(n-1, sum-i);

return lookup[n][sum] = ans;


}

// This is mainly a wrapper over countRec. It


// explicitly handles leading digit and calls
// countRec() for remaining n.
unsigned long long int finalCount(int n, int sum)
{
// Initialize all entries of lookup table
memset(lookup, -1, sizeof lookup);

// Initialize final answer


unsigned long long int ans = 0;

// Traverse through every digit from 1 to


// 9 and count numbers beginning with it
for (int i = 1; i <= 9; i++)
if (sum-i >= 0)
ans += countRec(n-1, sum-i);
return ans;
}

// Driver program
int main()
{
int n = 3, sum = 5;
cout << finalCount(n, sum);
return 0;
}

// A memoization based recursive program to count numbers


// with difference between odd and even digit sums as 1
#include<bits/stdc++.h>

using namespace std;

// A lookup table used for memoization.


unsigned long long int lookup[50][1000][1000][2];

// Memnoization based recursive function to count numbers


// with even and odd digit sum difference as 1. This function
// conisders leading zero as a digit
unsigned long long int countRec(int digits, int esum,
int osum, bool isOdd, int n)
{
// Base Case
if (digits == n)
return (esum - osum == 1);

// If current subproblem is already computed


if (lookup[digits][esum][osum][isOdd] != -1)
return lookup[digits][esum][osum][isOdd];

// Initialize result
unsigned long long int ans = 0;

// If current digit is odd, then add it to odd sum and recur


if (isOdd)
for (int i = 0; i <= 9; i++)
ans += countRec(digits+1, esum, osum+i, false, n);
else // Add to even sum and recur
for (int i = 0; i <= 9; i++)
ans += countRec(digits+1, esum+i, osum, true, n);

// Store current result in lookup table and return the same


return lookup[digits][esum][osum][isOdd] = ans;
}

// This is mainly a wrapper over countRec. It


// explicitly handles leading digit and calls
// countRec() for remaining digits.
unsigned long long int finalCount(int n)
{
// Initialize number digits considered so far
int digits = 0;

// Initialize all entries of lookup table


memset(lookup, -1, sizeof lookup);

// Initializa final answer


unsigned long long int ans = 0;

// Initialize even and odd sums


int esum = 0, osum = 0;

// Explicitly handle first digit and call recursive function


// countRec for remaining digits. Note that the first digit
// is considered as even digit.
for (int i = 1; i <= 9; i++)
ans += countRec(digits+1, esum + i, osum, true, n);

return ans;
}

// Driver program
int main()
{
int n = 3;
cout << "Coutn of "<<n << " digit numbers is " << finalCount(n);
return 0;
}
// C++ program to find maximum weight transformation
// of a given string
#include<bits/stdc++.h>
using namespace std;

// Returns wieght of the maximum weight


// transformation
int getMaxRec(string &str, int i, int n, int lookup[])
{
// Base case
if (i >= n) return 0;

//If this subproblem is already solved


if (lookup[i] != -1) return lookup[i];

// Don't make pair, so weight gained is 1


int ans = 1 + getMaxRec(str, i+1, n, lookup);

// If we can make pair


if (i+1 < n)
{
// If elements are dissmilar, weight gained is 4
if (str[i] != str[i+1])
ans = max(4 + getMaxRec(str, i+2, n, lookup),
ans);

// if elements are similar so for making a pair


// we toggle any of them. Since toggle cost is
// 1 so overall weight gain becomes 3
else ans = max(3 + getMaxRec(str, i+2, n, lookup),
ans);
}

// save and return maximum of above cases


return lookup[i] = ans;
}

// Initializes lookup table and calls getMaxRec()


int getMaxWeight(string str)
{
int n = str.length();

// Create and initialize lookup table


int lookup[n];
memset(lookup, -1, sizeof lookup);

// Call recursive function


return getMaxRec(str, 0, str.length(), lookup);
}

// Driver program
int main()
{
string str = "AAAAABB";
cout << "Maximum weight of a transformation of "
<< str << " is " << getMaxWeight(str);
return 0;
}

// C++ program to find the longest repeating


// subsequence
#include <iostream>
#include <string>
using namespace std;

int findLongestRepeatingSubSeq(string str)


{
int n = str.length();

// Create and initialize DP table


int dp[n+1][n+1];
for (int i=0; i<=n; i++)
for (int j=0; j<=n; j++)
dp[i][j] = 0;

// Fill dp table (similar to LCS loops)


for (int i=1; i<=n; i++)
{
for (int j=1; j<=n; j++)
{
// If characters match and indexes are not same
if (str[i-1] == str[j-1] && i!=j)
dp[i][j] = 1 + dp[i-1][j-1];
// If characters do not match
else
dp[i][j] = max(dp[i][j-1], dp[i-1][j]);
}
}
return dp[n][n];
}

// Driver Program
int main()
{
string str = "aabb";
cout << "The length of the largest subsequence that"
" repeats itself is : "
<< findLongestRepeatingSubSeq(str);
return 0;
}

// A Dynamic Programming based C++ program to count number of ways


// to cover a distance with 1, 2 and 3 steps
#include<iostream>
using namespace std;

int printCountDP(int dist)


{
int count[dist+1];
// Initialize base values. There is one way to cover 0 and 1
// distances and two ways to cover 2 distance
count[0] = 1, count[1] = 1, count[2] = 2;

// Fill the count array in bottom up manner


for (int i=3; i<=dist; i++)
count[i] = count[i-1] + count[i-2] + count[i-3];

return count[dist];
}

// driver program
int main()
{
int dist = 4;
cout << printCountDP(dist);
return 0;
}

// Returns length of the longest path beginning with mat[i][j].


// This function mainly uses lookup table dp[n][n]
int findLongestFromACell(int i, int j, int mat[n][n], int dp[n][n])
{
// Base case
if (i<0 || i>=n || j<0 || j>=n)
return 0;

// If this subproblem is already solved


if (dp[i][j] != -1)
return dp[i][j];

// Since all numbers are unique and in range from 1 to n*n,


// there is atmost one possible direction from any cell
if (j<n-1 && ((mat[i][j] +1) == mat[i][j+1]))
return dp[i][j] = 1 + findLongestFromACell(i,j+1,mat,dp);

if (j>0 && (mat[i][j] +1 == mat[i][j-1]))


return dp[i][j] = 1 + findLongestFromACell(i,j-1,mat,dp);

if (i>0 && (mat[i][j] +1 == mat[i-1][j]))


return dp[i][j] = 1 + findLongestFromACell(i-1,j,mat,dp);

if (i<n-1 && (mat[i][j] +1 == mat[i+1][j]))


return dp[i][j] = 1 + findLongestFromACell(i+1,j,mat,dp);

// If none of the adjacent fours is one greater


return dp[i][j] = 1;
}

// Returns length of the longest path beginning with any cell


int finLongestOverAll(int mat[n][n])
{
int result = 1; // Initialize result

// Create a lookup table and fill all entries in it as -1


int dp[n][n];
memset(dp, -1, sizeof dp);

// Compute longest path beginning from all cells


for (int i=0; i<n; i++)
{
for (int j=0; j<n; j++)
{
if (dp[i][j] == -1)
findLongestFromACell(i, j, mat, dp);

// Update result if needed


result = max(result, dp[i][j]);
}
}

return result;
}

// Driver program
int main()
{
int mat[n][n] = {{1, 2, 9},
{5, 3, 8},
{4, 6, 7}};
cout << "Length of the longest path is "
<< finLongestOverAll(mat);
return 0;
}

/ A Dynamic programming based C++ program to find number of


// non-negative solutions for a given linear equation
#include<bits/stdc++.h>
using namespace std;

// Returns counr of solutions for given rhs and coefficients


// coeff[0..n-1]
int countSol(int coeff[], int n, int rhs)
{
// Create and initialize a table to store results of
// subproblems
int dp[rhs+1];
memset(dp, 0, sizeof(dp));
dp[0] = 1;

// Fill table in bottom up manner


for (int i=0; i<n; i++)
for (int j=coeff[i]; j<=rhs; j++)
dp[j] += dp[j-coeff[i]];

return dp[rhs];
}

// Driver program
int main()
{
int coeff[] = {2, 2, 5};
int rhs = 4;
int n = sizeof(coeff)/sizeof(coeff[0]);
cout << countSol(coeff, n, rhs);
return 0;
}

// A Dynamic Programming based C++ program to count paths with


// exactly 'k' coins
#include <bits/stdc++.h>
#define R 3
#define C 3
#define MAX_K 1000
using namespace std;

int dp[R][C][MAX_K];

int pathCountDPRecDP(int mat[][C], int m, int n, int k)


{
// Base cases
if (m < 0 || n < 0) return 0;
if (m==0 && n==0) return (k == mat[m][n]);

// If this subproblem is already solved


if (dp[m][n][k] != -1) return dp[m][n][k];

// (m, n) can be reached either through (m-1, n) or


// through (m, n-1)
dp[m][n][k] = pathCountDPRecDP(mat, m-1, n, k-mat[m][n]) +
pathCountDPRecDP(mat, m, n-1, k-mat[m][n]);

return dp[m][n][k];
}

// This function mainly initializes dp[][][] and calls


// pathCountDPRecDP()
int pathCountDP(int mat[][C], int k)
{
memset(dp, -1, sizeof dp);
return pathCountDPRecDP(mat, R-1, C-1, k);
}

// Driver Program to test above functions


int main()
{
int k = 12;
int mat[R][C] = { {1, 2, 3},
{4, 6, 5},
{3, 2, 1}
};
cout << pathCountDP(mat, k);
return 0;
}
/ A Dynamic Programming based C++ program to find maximum
// number of coins that can be collected before hitting a
// dead end
#include<bits/stdc++.h>
using namespace std;
#define R 5
#define C 5

// to check whether current cell is out of the grid or not


bool isValid(int i, int j)
{
return (i >=0 && i < R && j >=0 && j < C);
}

// dir = 0 for left, dir = 1 for right. This function returns


// number of maximum coins that can be collected starting from
// (i, j).
int maxCoinsUtil(char arr[R][C], int i, int j, int dir,
int dp[R][C][2])
{
// If this is a invalid cell or if cell is a blocking cell
if (isValid(i,j) == false || arr[i][j] == '#')
return 0;

// If this subproblem is already solved than return the


// already evaluated answer.
if (dp[i][j][dir] != -1)
return dp[i][j][dir];

// Check if this cell contains the coin 'C' or if its 'E'.


dp[i][j][dir] = (arr[i][j] == 'C')? 1: 0;

// Get the maximum of two cases when you are facing right
// in this cell
if (dir == 1) // Direction is right
dp[i][j][dir] += max(maxCoinsUtil(arr, i+1, j, 0, dp), // Down
maxCoinsUtil(arr, i, j+1, 1, dp)); // Ahead in
rught

// Get the maximum of two cases when you are facing left
// in this cell
if (dir == 0) // Direction is left
dp[i][j][dir] += max(maxCoinsUtil(arr, i+1, j, 1, dp), // Down
maxCoinsUtil(arr, i, j-1, 0, dp)); // Ahead in
left

// return the answer


return dp[i][j][dir];
}

// This function mainly creates a lookup table and calls


// maxCoinsUtil()
int maxCoins(char arr[R][C])
{
// Create lookup table and initialize all values as -1
int dp[R][C][2];
memset(dp, -1, sizeof dp);

// As per the question initial cell is (0, 0) and direction


// is right
return maxCoinsUtil(arr, 0, 0, 1, dp);
}

// Driver program to test above function


int main()
{
char arr[R][C] = { {'E', 'C', 'C', 'C', 'C'},
{'C', '#', 'C', '#', 'E'},
{'#', 'C', 'C', '#', 'C'},
{'C', 'E', 'E', 'C', 'E'},
{'C', 'E', '#', 'C', 'E'}
};

cout << "Maximum number of collected coins is "


<< maxCoins(arr);

return 0;
}

//numbere of ways to partition a set


// A C++ program to find n'th Bell number
#include<iostream>
using namespace std;

int bellNumber(int n)
{
int bell[n+1][n+1];
bell[0][0] = 1;
for (int i=1; i<=n; i++)
{
// Explicitly fill for j = 0
bell[i][0] = bell[i-1][i-1];

// Fill for remaining values of j


for (int j=1; j<=i; j++)
bell[i][j] = bell[i-1][j-1] + bell[i][j-1];
}
return bell[n][0];
}

// Driver program
int main()
{
for (int n=0; n<=5; n++)
cout << "Bell Number " << n << " is "
<< bellNumber(n) << endl;
return 0;
}
// A C++ program to count number of partitions
// of a set with n elements into k subsets
#include<iostream>
using namespace std;

// Returns count of different partitions of n


// elements in k subsets
int countP(int n, int k)
{
// Base cases
if (n == 0 || k == 0 || k > n)
return 0;
if (k == 1 || k == n)
return 1;

// S(n+1, k) = k*S(n, k) + S(n, k-1)


return k*countP(n-1, k) + countP(n-1, k-1);
}

// Driver program
int main()
{
cout << countP(3, 2);
return 0;
}

// A Dynamic programming based C++ program to count derangements


#include <bits/stdc++.h>
using namespace std;

int countDer(int n)
{
// Create an array to store counts for subproblems
int der[n + 1];

// Base cases
der[0] = 1;
der[1] = 0;
der[2] = 1;

// Fill der[0..n] in bottom up manner using above


// recursive formula
for (int i=3; i<=n; ++i)
der[i] = (i-1)*(der[i-1] + der[i-2]);

// Return result for n


return der[n];
}

// Driver program
int main()
{
int n = 4;
cout << "Count of Derangements is " << countDer(n);
return 0;
// A Recursive C program to solve minimum sum partition
// problem.
#include <bits/stdc++.h>
using namespace std;

// Returns the minimum value of the difference of the two sets.


int findMin(int arr[], int n)
{
// Calculate sum of all elements
int sum = 0;
for (int i = 0; i < n; i++)
sum += arr[i];

// Create an array to store results of subproblems


bool dp[n+1][sum+1];

// Initialize first column as true. 0 sum is possible


// with all elements.
for (int i = 0; i <= n; i++)
dp[i][0] = true;

// Initialize top row, except dp[0][0], as false. With


// 0 elements, no other sum except 0 is possible
for (int i = 1; i <= sum; i++)
dp[0][i] = false;

// Fill the partition table in bottom up manner


for (int i=1; i<=n; i++)
{
for (int j=1; j<=sum; j++)
{
// If i'th element is excluded
dp[i][j] = dp[i-1][j];

// If i'th element is included


if (arr[i-1] <= j)
dp[i][j] |= dp[i-1][j-arr[i-1]];
}
}

// Initialize difference of two sums.


int diff = INT_MAX;

// Find the largest j such that dp[n][j]


// is true where j loops from sum/2 t0 0
for (int j=sum/2; j>=0; j--)
{
// Find the
if (dp[n][j] == true)
{
diff = sum-2*j;
break;
}
}
return diff;
}
// Driver program to test above function
int main()
{
int arr[] = {3, 1, 4, 2, 2, 1};
int n = sizeof(arr)/sizeof(arr[0]);
cout << "The minimum difference between 2 sets is "
<< findMin(arr, n);
return 0;
}

// C program to find longest Zig-Zag subsequence in


// an array
#include <stdio.h>
#include <stdlib.h>

// function to return max of two numbers


int max(int a, int b) { return (a > b) ? a : b; }

// Function to return longest Zig-Zag subsequence length


int zzis(int arr[], int n)
{
/*Z[i][0] = Length of the longest Zig-Zag subsequence
ending at index i and last element is greater
than its previous element
Z[i][1] = Length of the longest Zig-Zag subsequence
ending at index i and last element is smaller
than its previous element */
int Z[n][2];

/* Initialize all values from 1 */


for (int i = 0; i < n; i++)
Z[i][0] = Z[i][1] = 1;

int res = 1; // Initialize result

/* Compute values in bottom up manner */


for (int i = 1; i < n; i++)
{
// Consider all elements as previous of arr[i]
for (int j = 0; j < i; j++)
{
// If arr[i] is greater, then check with Z[j][1]
if (arr[j] < arr[i] && Z[i][0] < Z[j][1] + 1)
Z[i][0] = Z[j][1] + 1;

// If arr[i] is smaller, then check with Z[j][0]


if( arr[j] > arr[i] && Z[i][1] < Z[j][0] + 1)
Z[i][1] = Z[j][0] + 1;
}

/* Pick maximum of both values at index i */


if (res < max(Z[i][0], Z[i][1]))
res = max(Z[i][0], Z[i][1]);
}
return res;
}

/* Driver program */
int main()
{
int arr[] = { 10, 22, 9, 33, 49, 50, 31, 60 };
int n = sizeof(arr)/sizeof(arr[0]);
printf("Length of Longest Zig-Zag subsequence is %d\n",
zzis(arr, n) );
return 0;
}

// C++ program to count number of ways to arrange three


// types of balls such that no two balls of same color
// are adjacent to each other
#include<bits/stdc++.h>
using namespace std;
#define MAX 100

// table to store to store results of subproblems


int dp[MAX][MAX][MAX][3];

// Returns count of arrangements where last placed ball is


// 'last'. 'last' is 0 for 'p', 1 for 'q' and 2 for 'r'
int countWays(int p, int q, int r, int last)
{
// if number of balls of any color becomes less
// than 0 the number of ways arrangements is 0.
if (p<0 || q<0 || r<0)
return 0;

// If last ball required is of type P and the number


// of balls of P type is 1 while number of balls of
// other color is 0 the number of ways is 1.
if (p==1 && q==0 && r==0 && last==0)
return 1;

// Same case as above for 'q' and 'r'


if (p==0 && q==1 && r==0 && last==1)
return 1;
if (p==0 && q==0 && r==1 && last==2)
return 1;

// If this subproblem is already evaluated


if (dp[p][q][r][last] != -1)
return dp[p][q][r][last];

// if last ball required is P and the number of ways is


// the sum of number of ways to form sequence with 'p-1' P
// balls, q Q Balls and r R balls ending with Q and R.
if (last==0)
dp[p][q][r][last] = countWays(p-1,q,r,1) + countWays(p-1,q,r,2);

// Same as above case for 'q' and 'r'


else if (last==1)
dp[p][q][r][last] = countWays(p,q-1,r,0) + countWays(p,q-1,r,2);
else //(last==2)
dp[p][q][r][last] = countWays(p,q,r-1,0) + countWays(p,q,r-1,1);

return dp[p][q][r][last];
}

// Returns count of required arrangements


int countUtil(int p, int q, int r)
{
// Initialize 'dp' array
memset(dp, -1, sizeof(dp));

// Three cases arise:


return countWays(p, q, r, 0) + // Last required balls is type P
countWays(p, q, r, 1) + // Last required balls is type Q
countWays(p, q, r, 2); // Last required balls is type R
}

// Driver code to test above


int main()
{
int p = 1, q = 1, r = 1;
printf("%d", countUtil(p, q, r));
return 0;
}

// C++ program to find minimum time to finish tasks


// such that no two consecutive tasks are skipped.
#include <bits/stdc++.h>
using namespace std;

// arr[] represents time taken by n given tasks


int minTime(int arr[], int n)
{
// Corner Cases
if (n <= 0)
return 0;

// Initialize value for the case when there


// is only one task in task list.
int incl = arr[0]; // First task is included
int excl = 0; // First task is exluded

// Process remaining n-1 tasks


for (int i=1; i<n; i++)
{
// Time taken if current task is included
// There are two possibilities
// (a) Previous task is also included
// (b) Previous task is not included
int incl_new = arr[i] + min(excl, incl);

// Time taken when current task is not


// included. There is only one possibility
// that previous task is also included.
int excl_new = incl;

// Update incl and excl for next iteration


incl = incl_new;
excl = excl_new;
}

// Return maximum of two values for last task


return min(incl, excl);
}

// Driver code
int main()
{
int arr1[] = {10, 5, 2, 7, 10};
int n1 = sizeof(arr1)/sizeof(arr1[0]);
cout << minTime(arr1, n1) << endl;

int arr2[] = {10, 5, 7, 10};


int n2 = sizeof(arr2)/sizeof(arr2[0]);
cout << minTime(arr2, n2) << endl;

int arr3[] = {10, 5, 2, 4, 8, 6, 7, 10};


int n3 = sizeof(arr3)/sizeof(arr3[0]);
cout << minTime(arr3, n3) << endl;

return 0;
}

// A C++ Program to find length of the Longest Common


// Increasing Subsequence (LCIS)
#include<bits/stdc++.h>
using namespace std;

// Returns the length and the LCIS of two


// arrays arr1[0..n-1] and arr2[0..m-1] and
// prints LCIS
int LCIS(int arr1[], int n, int arr2[], int m)
{
// table[j] is going to store length of LCIS
// ending with arr2[j]. We initialize it as 0,
int table[m], parent[m];
for (int j=0; j<m; j++)
table[j] = 0;

// Traverse all elements of arr1[]


for (int i=0; i<n; i++)
{
// Initialize current length of LCIS
int current = 0, last = -1;

// For each element of arr1[], trvarse all


// elements of arr2[].
for (int j=0; j<m; j++)
{
// If both the array have same elements.
// Note that we don't break the loop here.
if (arr1[i] == arr2[j])
{
if (current + 1 > table[j])
{
table[j] = current + 1;
parent[j] = last;
}
}

/* Now seek for previous smaller common


element for current element of arr1 */
if (arr1[i] > arr2[j])
{
if (table[j] > current)
{
current = table[j];
last = j;
}
}
}
}

// The maximum value in table[] is out result


int result = 0, index = -1;
for (int i=0; i<m; i++)
{
if (table[i] > result)
{
result = table[i];
index = i;
}
}

// LCIS is going to store elements of LCIS


int lcis[result];
for (int i=0; index != -1; i++)
{
lcis[i] = arr2[index];
index = parent[index];
}

cout << "The LCIS is : ";


for (int i=result-1; i>=0; i--)
printf ("%d ", lcis[i]);

return result;
}

/* Driver program to test above function */


int main()
{
int arr1[] = {3, 4, 9, 1};
int arr2[] = {5, 3, 8, 9, 10, 2, 1};
int n = sizeof(arr1)/sizeof(arr1[0]);
int m = sizeof(arr2)/sizeof(arr2[0]);

cout << "\nLength of LCIS is "


<< LCIS(arr1, n, arr2, m);
return (0);
}

// A DP based C++ program to find maximum tasks.


#include<stdio.h>

// Returns the maximum among the 2 numbers


int max(int x, int y)
{
return (x > y ? x : y);
}

// Returns maximum amount of task that can be


// done till day n
int maxTasks(int high[], int low[], int n)
{
// An array task_dp that stores the maximum
// task done
int task_dp[n+1];

// If n = 0, no solution exists
task_dp[0] = 0;

// If n = 1, high effort task on that day will


// be the solution
task_dp[1] = high[0];

// Fill the entire array determining which


// task to choose on day i
for (int i = 2; i <= n; i++)
task_dp[i] = max(high[i-1] + task_dp[i-2],
low[i-1] + task_dp[i-1]);
return task_dp[n];
}

// Driver program to test above function


int main()
{
int n = 5;
int high[] = {3, 6, 8, 7, 6};
int low[] = {1, 5, 4, 5, 3};
printf("%d\n", maxTasks(high, low, n));
return 0;
}
// C++ program to find minimum adjustment cost of an array
#include <bits/stdc++.h>
using namespace std;

#define M 100

// Function to find minimum adjustment cost of an array


int minAdjustmentCost(int A[], int n, int target)
{
// dp[i][j] stores minimal adjustment cost on changing
// A[i] to j
int dp[n][M + 1];

// handle first element of array seperately


for (int j = 0; j <= M; j++)
dp[0][j] = abs(j - A[0]);

// do for rest elements of the array


for (int i = 1; i < n; i++)
{
// replace A[i] to j and calculate minimal adjustment
// cost dp[i][j]
for (int j = 0; j <= M; j++)
{
// initialize minimal adjustment cost to INT_MAX
dp[i][j] = INT_MAX;

// consider all k such that k >= max(j - target, 0) and


// k <= min(M, j + target) and take minimum
for (int k = max(j-target,0); k <= min(M,j+target); k++)
dp[i][j] = min(dp[i][j], dp[i - 1][k] + abs(A[i] - j));
}
}

// return minimum value from last row of dp table


int res = INT_MAX;
for (int j = 0; j <= M; j++)
res = min(res, dp[n - 1][j]);

return res;
}

// Driver Program to test above functions


int main()
{
int arr[] = {55, 77, 52, 61, 39, 6, 25, 60, 49, 47};
int n = sizeof(arr) / sizeof(arr[0]);
int target = 10;

cout << "Minimum adjustment cost is "


<< minAdjustmentCost(arr, n, target) << endl;

return 0;
}
// C++ program to find length of the longest geometric
// progression in a given set
#include <iostream>
#include <algorithm>
using namespace std;

// Returns length of the longest GP subset of set[]


int lenOfLongestGP(int set[], int n)
{
// Base cases
if (n < 2)
return n;
if (n == 2)
return (set[1] % set[0] == 0);

// Let us sort the set first


sort(set, set+n);

// An entry L[i][j] in this table stores LLGP with


// set[i] and set[j] as first two elements of GP
// and j > i.
int L[n][n];

// Initialize result (A single element is always a GP)


int llgp = 1;

// Initialize values of last column


for (int i = 0; i < n; ++i)
if (set[n-1] % set[i] == 0)
L[i][n-1] = 2;
else
L[i][n-1] = 1;

// Consider every element as second element of GP


for (int j = n - 2; j >= 1; --j)
{
// Search for i and k for j
int i = j - 1, k = j+1;
while (i>=0 && k <= n-1)
{
// Two cases when i, j and k don't form
// a GP.
if (set[i] * set[k] < set[j]*set[j])
++k;

else if (set[i] * set[k] > set[j]*set[j])


{
if (set[j] % set[i] == 0)
L[i][j] = 2;
else
L[i][j] = 1;
--i;
}
// i, j and k form GP, LLGP with i and j as
// first two elements is equal to LLGP with
// j and k as first two elements plus 1.
// L[j][k] must have been filled before as
// we run the loop from right side
else
{
L[i][j] = L[j][k] + 1;

// Update overall LLGP


if (L[i][j] > llgp)
llgp = L[i][j];

// Change i and k to fill more L[i][j]


// values for current j
--i;
++k;
}
}

// If the loop was stopped due to k becoming


// more than n-1, set the remaining entties
// in column j as 1 or 2 based on divisibility
// of set[j] by set[i]
while (i >= 0)
{
if (set[j] % set[i] == 0)
L[i][j] = 2;
else
L[i][j] = 1;
--i;
}
}

// Return result
return llgp;
}

// Driver code
int main()
{
int set1[] = {1, 3, 9, 27, 81, 243};
int n1 = sizeof(set1)/sizeof(set1[0]);
cout << lenOfLongestGP(set1, n1) << "\n";

int set2[] = {1, 3, 4, 9, 7, 27};


int n2 = sizeof(set2)/sizeof(set2[0]);
cout << lenOfLongestGP(set2, n2) << "\n";

int set3[] = {2, 3, 5, 7, 11, 13};


int n3 = sizeof(set3)/sizeof(set3[0]);
cout << lenOfLongestGP(set3, n3) << "\n";

return 0;
}
/* C++ code to find minimum cost to make two strings
identical */
#include<bits/stdc++.h>
using namespace std;

/* Returns length of LCS for X[0..m-1], Y[0..n-1] */


int lcs(char *X, char *Y, int m, int n)
{
int L[m+1][n+1];

/* Following steps build L[m+1][n+1] in bottom


up fashion. Note that L[i][j] contains length
of LCS of X[0..i-1] and Y[0..j-1] */
for (int i=0; i<=m; i++)
{
for (int j=0; j<=n; j++)
{
if (i == 0 || j == 0)
L[i][j] = 0;

else if (X[i-1] == Y[j-1])


L[i][j] = L[i-1][j-1] + 1;

else
L[i][j] = max(L[i-1][j], L[i][j-1]);
}
}

/* L[m][n] contains length of LCS for X[0..n-1] and


Y[0..m-1] */
return L[m][n];
}

// Returns cost of making X[] and Y[] identical. costX is


// cost of removing a character from X[] and costY is cost
// of removing a character from Y[]/
int findMinCost(char X[], char Y[], int costX, int costY)
{
// Find LCS of X[] and Y[]
int m = strlen(X), n = strlen(Y);
int len_LCS = lcs(X, Y, m, n);

// Cost of making two strings identical is SUM of


// following two
// 1) Cost of removing extra characters
// from first string
// 2) Cost of removing extra characters from
// second string
return costX * (m - len_LCS) +
costY * (n - len_LCS);
}

/* Driver program to test above function */


int main()
{
char X[] = "ef";
char Y[] = "gh";
cout << "Minimum Cost to make two strings "
<< " identical is = " << findMinCost(X, Y, 10, 20);
return 0;
}
// A Dynamic Programming based C++ program to find the
// number of times the second string occurs in the first
// string, whether continuous or discontinuous
#include <iostream>
using namespace std;

// Iterative DP function to find the number of times


// the second string occurs in the first string,
// whether continuous or discontinuous
int count(string a, string b)
{
int m = a.length();
int n = b.length();

// Create a table to store results of sub-problems


int lookup[m + 1][n + 1] = { { 0 } };

// If first string is empty


for (int i = 0; i <= n; ++i)
lookup[0][i] = 0;

// If second string is empty


for (int i = 0; i <= m; ++i)
lookup[i][0] = 1;

// Fill lookup[][] in bottom up manner


for (int i = 1; i <= m; i++)
{
for (int j = 1; j <= n; j++)
{
// If last characters are same, we have two
// options -
// 1. consider last characters of both strings
// in solution
// 2. ignore last character of first string
if (a[i - 1] == b[j - 1])
lookup[i][j] = lookup[i - 1][j - 1] +
lookup[i - 1][j];

else
// If last character are different, ignore
// last character of first string
lookup[i][j] = lookup[i - 1][j];
}
}

return lookup[m][n];
}

// Driver code
int main()
{
string a = "GeeksforGeeks";
string b = "Gks";

cout << count(a, b);

return 0;
}

// C++ program to count number of ways to connect n (where n


// is even) points on a circle such that no two connecting
// lines cross each other and every point is connected with
// one other point.
#include<iostream>
using namespace std;

// A dynamic programming based function to find nth


// Catalan number
unsigned long int catalanDP(unsigned int n)
{
// Table to store results of subproblems
unsigned long int catalan[n+1];

// Initialize first two values in table


catalan[0] = catalan[1] = 1;

// Fill entries in catalan[] using recursive formula


for (int i=2; i<=n; i++)
{
catalan[i] = 0;
for (int j=0; j<i; j++)
catalan[i] += catalan[j] * catalan[i-j-1];
}

// Return last entry


return catalan[n];
}

// Returns count of ways to connect n points on a circle


// such that no two connecting lines cross each other and
// every point is connected with one other point.
unsigned long int countWays(unsigned long int n)
{
// Throw error if n is odd
if (n & 1)
{
cout << "Invalid";
return 0;
}

// Else return n/2'th Catalan number


return catalanDP(n/2);
}

// Driver program to test above function


int main()
{
cout << countWays(6) << " ";
return 0;
}

// C++ program to count number of distinct


// subsequences of a given string.
#include <bits/stdc++.h>
using namespace std;
const int MAX_CHAR = 256;

// Returns count of distinct sunsequences of str.


int countSub(string str)
{
// Create an array to store index
// of last
vector<int> last(MAX_CHAR, -1);

// Length of input string


int n = str.length();

// dp[i] is going to store count of distinct


// subsequences of length i.
int dp[n+1];

// Empty substring has only one subsequence


dp[0] = 1;

// Traverse through all lengths from 1 to n.


for (int i=1; i<=n; i++)
{
// Number of subsequences with substring
// str[0..i-1]
dp[i] = 2*dp[i-1];

// If current character has appeared


// before, then remove all subsequences
// ending with previous occurrence.
if (last[str[i-1]] != -1)
dp[i] = dp[i] - dp[last[str[i-1]]];

// Mark occurrence of current character


last[str[i-1]] = (i-1);
}

return dp[n];
}

// Driver code
int main()
{
cout << countSub("gfg");
return 0;
}
// A Dynamic Programming based C++ program to
// find minimum possible sum of elements of array
// such that an element out of every three
// consecutive is picked.
#include <iostream>
using namespace std;

// A utility function to find minimum of


// 3 elements
int minimum(int a, int b, int c)
{
return min(min(a, b), c);
}

// Returns minimum possible sum of elements such


// that an element out of every three consecutive
// elements is picked.
int findMinSum(int arr[], int n)
{
// Create a DP table to store results of
// subpriblems. sum[i] is going to store
// minimum possible sum when arr[i] is
// part of the solution.
int sum[n];

// When there are less than or equal to


// 3 elements
sum[0] = arr[0];
sum[1] = arr[1];
sum[2] = arr[2];

// Iterate through all other elements


for (int i=3; i<n; i++)
sum[i] = arr[i] +
minimum(sum[i-3], sum[i-2], sum[i-1]);

return minimum(sum[n-1], sum[n-2], sum[n-3]);


}

// Driver code
int main()
{
int arr[] = {1, 2, 3, 20, 2, 10, 1};
int n = sizeof(arr)/sizeof(arr[0]);
cout << "Min Sum is " << findMinSum(arr, n);
return 0;
}
// C++ program to find the longest repeated
// non-overlapping substring
#include<bits/stdc++.h>
using namespace std;

// Returns the longest repeating non-overlapping


// substring in str
string longestRepeatedSubstring(string str)
{
int n = str.length();
int LCSRe[n+1][n+1];

// Setting all to 0
memset(LCSRe, 0, sizeof(LCSRe));

string res; // To store result


int res_length = 0; // To store length of result

// building table in bottom-up manner


int i, index = 0;
for (i=1; i<=n; i++)
{
for (int j=i+1; j<=n; j++)
{
// (j-i) > LCSRe[i-1][j-1] to remove
// overlapping
if (str[i-1] == str[j-1] &&
LCSRe[i-1][j-1] < (j - i))
{
LCSRe[i][j] = LCSRe[i-1][j-1] + 1;

// updating maximum length of the


// substring and updating the finishing
// index of the suffix
if (LCSRe[i][j] > res_length)
{
res_length = LCSRe[i][j];
index = max(i, index);
}
}
else
LCSRe[i][j] = 0;
}
}

// If we have non-empty result, then insert all


// characters from first character to last
// character of string
if (res_length > 0)
for (i = index - res_length + 1; i <= index; i++)
res.push_back(str[i-1]);

return res;
}

// Driver program to test the above function


int main()
{
string str = "geeksforgeeks";
cout << longestRepeatedSubstring(str);
return 0;
}

// C++ program to find number of permutation with


// K inversion using Memoization
#include <bits/stdc++.h>
using namespace std;

// Limit on N and K
const int M = 100

// 2D array memo for stopping solving same problem


// again
int memo[M][M];

// method recursively calculates permutation with


// K inversion
int numberOfPermWithKInversion(int N, int K)
{
// base cases
if (N == 0)
return 0;
if (K == 0)
return 1;

// if already solved then return result directly


if (memo[N][K] != 0)
return memo[N][K];

// calling recursively all subproblem of


// permutation size N - 1
int sum = 0;
for (int i = 0; i <= K; i++)
{
// Call recursively only if total inversion
// to be made are less than size
if (i <= N - 1)
sum += numberOfPermWithKInversion(N-1, K-i);
}

// store result into memo


memo[N][K] = sum;

return sum;
}

// Driver code to test above methods


int main()
{
int N = 4;
int K = 2;
cout << numberOfPermWithKInversion(N, K);
return 0;
}

/**
* http://www.geeksforgeeks.org/dynamic-programming-set-15-longest-bitonic-
subsequence/
*/
public class BitonicSequence {

public int longestSequence(int arr[]){


int lis[] = new int[arr.length];
int lds[] = new int[arr.length];
for(int i=0; i < arr.length; i++){
lis[i] = 1;
lds[i] = 1;
}
for(int i=1 ; i < arr.length; i++){
for(int j=0; j < i ; j++){
if(arr[i] > arr[j]){
lis[i] = Math.max(lis[i], lis[j] + 1);
}
}
}

for(int i = arr.length-2; i >=0 ; i--){


for(int j = arr.length-1; j > i; j--){
if(arr[i] > arr[j]){
lds[i] = Math.max(lds[i], lds[j] + 1);
}
}
}
int max = 0;
for(int i=0; i < arr.length; i++){
if(max < lis[i] + lds[i]-1){
max = lis[i] + lds[i] -1;
}
}
return max;
}

public static void main(String args[]){


BitonicSequence bs = new BitonicSequence();
int[] arr = {1,4,3,7,2,1,8,11,13,0};
int r = bs.longestSequence(arr);
System.out.print(r);

}
}
package com.interview.dynamic;

/**
* Date 03/02/2016
* @author Tushar Roy
*
* Given n balloons, indexed from 0 to n-1. Each balloon is painted with a number on
it represented
* by array nums. You are asked to burst all the balloons. If the you burst balloon i
you will
* get nums[left] * nums[i] * nums[right] coins. Here left and right are adjacent
indices of i. After the burst,
* the left and right then becomes adjacent.
* Find the maximum coins you can collect by bursting the balloons wisely.
*
* Time complexity O(n^3)
* Space complexity O(n^2)
*
* Reference
* https://leetcode.com/problems/burst-balloons/
*/
public class BurstBalloons {

/**
* Dynamic programming solution.
*/
public int maxCoinsBottomUpDp(int[] nums) {

int T[][] = new int[nums.length][nums.length];

for (int len = 1; len <= nums.length; len++) {


for (int i = 0; i <= nums.length - len; i++) {
int j = i + len - 1;
for (int k = i; k <= j; k++) {
//leftValue/rightValue is initially 1. If there is element on
// left/right of k then left/right value will take that value.
int leftValue = 1;
int rightValue = 1;
if (i != 0) {
leftValue = nums[i-1];
}
if (j != nums.length -1) {
rightValue = nums[j+1];
}

//before is initially 0. If k is i then before will


//stay 0 otherwise it gets value T[i][k-1]
//after is similarly 0 initially. if k is j then after will
//stay 0 other will get value T[k+1][j]
int before = 0;
int after = 0;
if (i != k) {
before = T[i][k-1];
}
if (j != k) {
after = T[k+1][j];
}
T[i][j] = Math.max(leftValue * nums[k] * rightValue + before +
after,
T[i][j]);
}
}
}
return T[0][nums.length - 1];
}
/**
* Recursive solution.
*/
public int maxCoinsRec(int nums[]) {
int[] nums1 = new int[nums.length + 2];
nums1[0] = 1;
nums1[nums1.length - 1] = 1;
for (int i = 0; i < nums.length; i++) {
nums1[i+1] = nums[i];
}
return maxCoinsRecUtil(nums1);
}

private int maxCoinsRecUtil(int[] nums) {


if (nums.length == 2) {
return 0;
}

int max = 0;
for (int i = 1; i < nums.length - 1; i++) {
int val = nums[i - 1]*nums[i]*nums[i+1] +
maxCoinsRecUtil(formNewArray(nums, i));
if (val > max) {
max = val;
}
}
return max;

private int[] formNewArray(int[] input, int doNotIncludeIndex) {


int[] newArray = new int[input.length - 1];
int index = 0;
for (int i = 0; i < input.length; i++) {
if (i == doNotIncludeIndex) {
continue;
}
newArray[index++] = input[i];
}
return newArray;
}

public static void main(String args[]) {


BurstBalloons bb = new BurstBalloons();
int input[] = {2, 4, 3, 5};
System.out.print(bb.maxCoinsBottomUpDp(input));
}
}
* Given a total and coins of certain denominations find number of ways total
* can be formed from coins assuming infinity supply of coins
*
* References:
* http://www.geeksforgeeks.org/dynamic-programming-set-7-coin-change/
*/
public class CoinChanging {

public int numberOfSolutions(int total, int coins[]){


int temp[][] = new int[coins.length+1][total+1];
for(int i=0; i <= coins.length; i++){
temp[i][0] = 1;
}
for(int i=1; i <= coins.length; i++){
for(int j=1; j <= total ; j++){
if(coins[i-1] > j){
temp[i][j] = temp[i-1][j];
}
else{
temp[i][j] = temp[i][j-coins[i-1]] + temp[i-1][j];
}
}
}
return temp[coins.length][total];
}

/**
* Space efficient DP solution
*/
public int numberOfSolutionsOnSpace(int total, int arr[]){

int temp[] = new int[total+1];

temp[0] = 1;
for(int i=0; i < arr.length; i++){
for(int j=1; j <= total ; j++){
if(j >= arr[i]){
temp[j] += temp[j-arr[i]];
}
}
}
return temp[total];
}

/**
* This method actually prints all the combination. It takes exponential time.
*/
public void printCoinChangingSolution(int total,int coins[]){
List<Integer> result = new ArrayList<>();
printActualSolution(result, total, coins, 0);
}
private void printActualSolution(List<Integer> result,int total,int coins[],int pos){
if(total == 0){
for(int r : result){
System.out.print(r + " ");
}
System.out.print("\n");
}
for(int i=pos; i < coins.length; i++){
if(total >= coins[i]){
result.add(coins[i]);
printActualSolution(result,total-coins[i],coins,i);
result.remove(result.size()-1);
}
}
}

public static void main(String args[]){


CoinChanging cc = new CoinChanging();
int total = 15;
int coins[] = {3,4,6,7,9};
System.out.println(cc.numberOfSolutions(total, coins));
System.out.println(cc.numberOfSolutionsOnSpace(total, coins));
cc.printCoinChangingSolution(total, coins);
}
}
package com.interview.dynamic;

import java.text.Format;
import java.util.HashMap;
import java.util.Map;

/**
* Date 08/12/2013
* @author Tushar Roy
*
* Given a total and coins of certain denomination with infinite supply, what is the minimum number
* of coins it takes to form this total.
*
* Time complexity - O(coins.size * total)
* Space complexity - O(coins.size * total)
*
* Youtube video -
* Topdown DP - https://youtu.be/Kf_M7RdHr1M
* Bottom up DP - https://youtu.be/Y0ZqKpToTic
*/
public class CoinChangingMinimumCoin {

/**
* Top down dynamic programing. Using map to store intermediate results.
* Returns Integer.MAX_VALUE if total cannot be formed with given coins
*/
public int minimumCoinTopDown(int total, int coins[], Map<Integer, Integer> map) {

//if total is 0 then there is nothing to do. return 0.


if ( total == 0 ) {
return 0;
}

//if map contains the result means we calculated it before. Lets return that value.
if ( map.containsKey(total) ) {
return map.get(total);
}

//iterate through all coins and see which one gives best result.
int min = Integer.MAX_VALUE;
for ( int i=0; i < coins.length; i++ ) {
//if value of coin is greater than total we are looking for just continue.
if( coins[i] > total ) {
continue;
}
//recurse with total - coins[i] as new total
int val = minimumCoinTopDown(total - coins[i], coins, map);

//if val we get from picking coins[i] as first coin for current total is less
// than value found so far make it minimum.
if( val < min ) {
min = val;
}
}

//if min is MAX_VAL dont change it. Just result it as is. Otherwise add 1 to it.
min = (min == Integer.MAX_VALUE ? min : min + 1);

//memoize the minimum for current total.


map.put(total, min);
return min;
}

/**
* Bottom up way of solving this problem.
* Keep input sorted. Otherwise temp[j-arr[i]) + 1 can become Integer.Max_value + 1 which
* can be very low negative number
* Returns Integer.MAX_VALUE - 1 if solution is not possible.
*/
public int minimumCoinBottomUp(int total, int coins[]){
int T[] = new int[total + 1];
int R[] = new int[total + 1];
T[0] = 0;
for(int i=1; i <= total; i++){
T[i] = Integer.MAX_VALUE-1;
R[i] = -1;
}
for(int j=0; j < coins.length; j++){
for(int i=1; i <= total; i++){
if(i >= coins[j]){
if (T[i - coins[j]] + 1 < T[i]) {
T[i] = 1 + T[i - coins[j]];
R[i] = j;
}
}
}
}
printCoinCombination(R, coins);
return T[total];
}

private void printCoinCombination(int R[], int coins[]) {


if (R[R.length - 1] == -1) {
System.out.print("No solution is possible");
return;
}
int start = R.length - 1;
System.out.print("Coins used to form total ");
while ( start != 0 ) {
int j = R[start];
System.out.print(coins[j] + " ");
start = start - coins[j];
}
System.out.print("\n");
}

public static void main ( String args[] ) {


int total = 13;
int coins[] = {7, 3, 2, 6};
CoinChangingMinimumCoin cc = new CoinChangingMinimumCoin();
Map<Integer, Integer> map = new HashMap<>();
int topDownValue = cc.minimumCoinTopDown(total, coins, map);
int bottomUpValue = cc.minimumCoinBottomUp(total, coins);

System.out.print(String.format("Bottom up and top down result %s %s", bottomUpValue,


topDownValue));

}
}
package com.interview.dynamic;

/**
* http://www.geeksforgeeks.org/count-number-binary-strings-without-consecutive-1s/
* It is really a straight up fibonacci series with values
* 1,2,3,5,8,13....
* Look how we assign a[i] value of a[i-1] + b[i-1] and then b[i] becomes a[i]
*/
public class CountNumberOfBinaryWithoutConsecutive1s {

public int count(int n){


int a[] = new int[n];
int b[] = new int[n];

a[0] = 1;
b[0] = 1;

for(int i=1; i < n; i++){


a[i] = a[i-1] + b[i-1];
b[i] = a[i-1];
}

return a[n-1] + b[n-1];


}

public int countSimple(int n){


int a = 1;
int b = 1;

for(int i=1; i < n; i++){


int tmp = a;
a = a + b;
b = tmp;
}

return a + b;
}

public static void main(String args[]){


CountNumberOfBinaryWithoutConsecutive1s cnb = new
CountNumberOfBinaryWithoutConsecutive1s();
System.out.println(cnb.count(5));
}
}
package com.interview.dynamic;

/**
* http://www.geeksforgeeks.org/program-nth-catalan-number/
* Count number of binary search tree created for array of size n
*/
public class CountNumberOfTreesInBST {

int countTreesRec(int numKeys) {


if (numKeys <=1) {
return(1);
}
else {
int sum = 0;
int left, right, root;
for (root=1; root<=numKeys; root++) {
left = countTreesRec(root - 1);
right = countTreesRec(numKeys - root);
sum += left*right;
}
return(sum);
}
}

public int countTrees(int n){


int T[] = new int[n+1];
T[0] = 1;
T[1] = 1;
for(int i=2; i <= n; i++){
for(int j=0; j <i; j++){
T[i] += T[j]*T[i-j-1];
}
}
return T[n];
}
public static void main(String args[]){
CountNumberOfTreesInBST cnt = new CountNumberOfTreesInBST();
System.out.println(cnt.countTrees(3));
System.out.println(cnt.countTrees(4));
}
}

package com.interview.dynamic;

* Given a rod with markings. Cut the rod along markings but reduce the cost of
cutting.
* Cost if cutting is proportional to the length of rod being cut.
*
* Solve is using top down dynamic programming. Memoize minimum cost of cutting
between marking
* start to end. To calculate the value try all markings b/w start to end.
*
*/
public class CutRodToMinimizeCost {

public int cutRodToMinimizeCost(int [] markings, int total) {


int T[][] = new int[total+1][total+1];
for(int i = 0 ; i < T.length; i++) {
for(int j=0; j < T[i].length ; j++) {
T[i][j] = -1;
}
}
return cutRodToMinimizeCost(markings, 0, total, T);
}
private int cutRodToMinimizeCost(int[] markings, int start, int end, int T[][]){

if(T[start][end] != -1) {
return T[start][end];
}

int i;
for(i=0; i < markings.length; i++){
if(start < markings[i]) {
break;
}
}
if(i == markings.length) {
T[start][end] = 0;
return 0;
}

int j;
for(j=markings.length -1; j >= 0; j--){
if(end > markings[j]) {
break;
}
}
if(j == -1) {
T[start][end] = 0;
return 0;
}
if(i == j){
T[start][end] = end - start;
return end - start;
}
int cost = end - start;
int minCost = Integer.MAX_VALUE;
for(int k=i; k <= j; k++) {
int c1 = cutRodToMinimizeCost(markings, start, markings[k], T);
int c2 = cutRodToMinimizeCost(markings, markings[k], end, T);
if(c1 == Integer.MAX_VALUE || c2 == Integer.MAX_VALUE) {
continue;
}
if(minCost > c1 + c2){
minCost = c1 + c2;
}
}
if(minCost == Integer.MAX_VALUE) {
T[start][end] = Integer.MAX_VALUE;
return Integer.MAX_VALUE;
}
T[start][end] = cost + minCost;
return cost + minCost;
}

public static void main(String args[]) {


int markings[] = {2,3,6,7};
CutRodToMinimizeCost cr = new CutRodToMinimizeCost();
int cost = cr.cutRodToMinimizeCost(markings, 8);
System.out.println(cost);
}
}

package com.interview.dynamic;

/**
* http://www.geeksforgeeks.org/dynamic-programming-set-13-cutting-a-rod/
*/
public class CuttingRod {

public int maxValue(int price[]){


int max[] = new int[price.length+1];
for(int i=1; i <= price.length; i++){
for(int j=i; j <= price.length; j++){
max[j] = Math.max(max[j], max[j-i] + price[i-1]);
}
}
return max[price.length];
}

public int maxValue1(int price[]){


int max[] = new int[price.length+1];
for(int i=1; i <= price.length; i++){
max[i] = price[i-1];
}
for(int i=1 ; i <= price.length; i++){
for(int j=1; j < i ; j++){
max[i] = Math.max(max[i], max[i-j] + max[j]);
}
}
return max[price.length];
}

public int recursiveMaxValue(int price[],int len){


if(len <= 0){
return 0;
}
int maxValue = 0;
for(int i=0; i < len;i++){
int val = price[i] + recursiveMaxValue(price, len-i-1);
if(maxValue < val){
maxValue = val;
}
}
return maxValue;
}
public static void main(String args[]){
CuttingRod cr =new CuttingRod();
int[] price = {3,5,8,9,10,20,22,25};
long t1 = System.currentTimeMillis();
int r = cr.recursiveMaxValue(price,8);
long t2 = System.currentTimeMillis();
System.out.println(r);
System.out.println(t2 - t1);
}
}
* A message containing letters from A-Z is being encoded to numbers using the following mapping:
* 1 -> A
* 2 -> B
* 3 -> C
* 26-> Z
* Given an encoded message containing digits, determine the total number of ways to decode it.
*
* https://leetcode.com/problems/decode-ways/
*/
public class DecodeWays {

public int numDecodings(String s) {


if (s.length() == 0) {
return 0;
}
Map<Integer, Integer> count = new HashMap<>();
return numDecodingsUtil(s, 0, count);
}

public int numDecodingsUtil(String s, int start, Map<Integer, Integer> count) {


if (s.length() == start) {
return 1;
}
if (count.containsKey(start)) {
return count.get(start);
}
String s1 = s.substring(start, start + 1);
if (s1.equals("0")) {
count.put(start, 0);
return 0;
}
int c1 = numDecodingsUtil(s, start + 1, count);

int c2 = 0;
if (start < s.length() - 1) {
s1 = s.substring(start, start + 2);
if (Integer.valueOf(s1) <= 26) {
c2 = numDecodingsUtil(s, start + 2, count);
}
}
count.put(start, c1 + c2);
return c1 + c2;
}
}
package com.interview.dynamic;
/**
* @author Tushar Roy
* http://www.geeksforgeeks.org/dice-throw-problem/
* This solution assumes that 1,2,1 is different from 2,1,1 which is different from
1,1 2
* so total 3 ways are possible
*/
public class DiceThrowWays {

public int numberOfWays(int n, int f, int k){

int T[][] = new int[n+1][k+1];


T[0][0] = 1;
/* for(int i=0; i < T.length; i++){
T[0][i] = 1;
}*/

for(int i=1; i <= n; i++){


for(int j =1; j <= i*f && j <= k ; j++){
if(j == i){
T[i][j] = 1;
continue;
}
if(j < i){
continue;
}
for(int l =1; l <=f ;l++){
if(j >= l){
T[i][j] += T[i-1][j-l];
}
}
}
}
return T[n][k];
}

public static void main(String args[]){


DiceThrowWays dtw = new DiceThrowWays();
System.out.println(dtw.numberOfWays(3, 3, 6));
}
}
package com.interview.dynamic;

* Given a string S and a string T, count the number of distinct subsequences of T in


S.
*

public class DistinctSubsequence {


public int numDistinct(String s, String t) {
if (s.length() == 0 || t.length() == 0) {
return 0;
}
int[][] T = new int[t.length() + 1][s.length() + 1];
for (int i = 0; i < T[0].length; i++) {
T[0][i] = 1;
}
for (int i = 1; i < T.length; i++) {
for (int j = 1; j < T[0].length; j++) {
if (s.charAt(j - 1) == t.charAt(i - 1)) {
T[i][j] = T[i-1][j-1] + T[i][j-1];
} else {
T[i][j] = T[i][j-1];
}
}
}
return T[t.length()][s.length()];
}

public static void main(String args[]) {


DistinctSubsequence ds = new DistinctSubsequence();
System.out.println(ds.numDistinct("abdacgblc", "abc"));
}
}
package com.interview.dynamic;

import java.util.List;

* Given two strings how many minimum edits(update, delete or add) is needed to
convert one string to another
*
* Time complexity is O(m*n)
* Space complexity is O(m*n)
*
public class EditDistance {

/**
* Uses recursion to find minimum edits
*/
public int recEditDistance(char[] str1, char str2[], int len1,int len2){

if(len1 == str1.length){
return str2.length - len2;
}
if(len2 == str2.length){
return str1.length - len1;
}
return min(recEditDistance(str1, str2, len1 + 1, len2 + 1) + str1[len1] ==
str2[len2] ? 0 : 1, recEditDistance(str1, str2, len1, len2 + 1) + 1,
recEditDistance(str1, str2, len1 + 1, len2) + 1);
}

/**
* Uses bottom up DP to find the edit distance
*/
public int dynamicEditDistance(char[] str1, char[] str2){
int temp[][] = new int[str1.length+1][str2.length+1];

for(int i=0; i < temp[0].length; i++){


temp[0][i] = i;
}

for(int i=0; i < temp.length; i++){


temp[i][0] = i;
}

for(int i=1;i <=str1.length; i++){


for(int j=1; j <= str2.length; j++){
if(str1[i-1] == str2[j-1]){
temp[i][j] = temp[i-1][j-1];
}else{
temp[i][j] = 1 + min(temp[i-1][j-1], temp[i-1][j], temp[i][j-1]);
}
}
}
printActualEdits(temp, str1, str2);
return temp[str1.length][str2.length];

/**
* Prints the actual edits which needs to be done.
*/
public void printActualEdits(int T[][], char[] str1, char[] str2) {
int i = T.length - 1;
int j = T[0].length - 1;
while(true) {
if (i == 0 || j == 0) {
break;
}
if (str1[i-1] == str2[j-1]) {
i = i-1;
j = j-1;
} else if (T[i][j] == T[i-1][j-1] + 1){
System.out.println("Edit " + str2[j-1] + " in string2 to " + str1[i-
1] + " in string1");
i = i-1;
j = j-1;
} else if (T[i][j] == T[i-1][j] + 1) {
System.out.println("Delete in string1 " + str1[i-1]);
i = i-1;
} else if (T[i][j] == T[i][j-1] + 1){
System.out.println("Delete in string2 " + str2[j-1]);
j = j -1;
} else {
throw new IllegalArgumentException("Some wrong with given data");
}

}
}

private int min(int a,int b, int c){


int l = Math.min(a, b);
return Math.min(l, c);
}
public static void main(String args[]){
String str1 = "azced";
String str2 = "abcdef";
EditDistance editDistance = new EditDistance();
int result = editDistance.dynamicEditDistance(str1.toCharArray(),
str2.toCharArray());
System.out.print(result);
}

}
package com.interview.dynamic;

/**
* http://www.geeksforgeeks.org/dynamic-programming-set-11-egg-dropping-puzzle/
*/
public class EggDropping {

public int calculate(int eggs, int floors){

int T[][] = new int[eggs+1][floors+1];


int c =0;
for(int i=0; i <= floors; i++){
T[1][i] = i;
}

for(int e = 2; e <= eggs; e++){


for(int f = 1; f <=floors; f++){
T[e][f] = Integer.MAX_VALUE;
for(int k = 1; k <=f ; k++){
c = 1 + Math.max(T[e-1][k-1], T[e][f-k]);
if(c < T[e][f]){
T[e][f] = c;
}
}
}
}
return T[eggs][floors];
}

public int calculateRecursive(int eggs, int floors){


if(eggs == 1){
return floors;
}
if(floors == 0){
return 0;
}
int min = 1000;
for(int i=1; i <= floors; i++){
int val = 1 + Math.max(calculateRecursive(eggs-1, i-
1),calculateRecursive(eggs, floors-i));
if(val < min){
min = val;
}
}
return min;
}

public static void main(String args[]){


EggDropping ed = new EggDropping();
int r = ed.calculate(3,100);
System.out.println(r);
}
}
package com.interview.dynamic;

/**
* Date 03/11/2016
* @author Tushar Roy
*
* Given a 2D array find the sum in given range defining a rectangle.
*
* Time complexity construction O(n*m)
* Time complexity of query O(1)
* Space complexity is O(n*m)
*
* Reference
* https://leetcode.com/problems/range-sum-query-2d-immutable/
*/
public class Immutable2DSumRangeQuery {
private int[][] T;

public Immutable2DSumRangeQuery(int[][] matrix) {


int row = 0;
int col = 0;
if (matrix.length != 0) {
row = matrix.length;
col = matrix[0].length;
}
T = new int[row + 1][col + 1];
for (int i = 1; i < T.length; i++) {
for (int j = 1; j < T[0].length; j++) {
T[i][j] = T[i - 1][j] + T[i][j - 1] + matrix[i - 1][j - 1] - T[i -
1][j - 1];
}
}
}

public int sumQuery(int row1, int col1, int row2, int col2) {
row1++;
col1++;
row2++;
col2++;
return T[row2][col2] - T[row1 - 1][col2] - T[row2][col1 - 1] + T[row1 -
1][col1 - 1];
}

public static void main(String args[]) {


int[][] input = {{3, 0, 1, 4, 2},
{5, 6, 3, 2, 1},
{1, 2, 0, 1, 5},
{4, 1, 0, 1, 7},
{1, 0, 3, 0, 5}};

int[][] input1 = {{2,0,-3,4}, {6, 3, 2, -1}, {5, 4, 7, 3}, {2, -6, 8, 1}};
Immutable2DSumRangeQuery isr = new Immutable2DSumRangeQuery(input1);
System.out.println(isr.sumQuery(1, 1, 2, 2));
}
}
package com.interview.dynamic;

/**
http://www.geeksforgeeks.org/dynamic-programming-set-4-longest-common-subsequence/
*/
public class LongestCommonSubsequence {

public int lcs(char str1[],char str2[],int len1, int len2){

if(len1 == str1.length || len2 == str2.length){


return 0;
}
if(str1[len1] == str2[len2]){
return 1 + lcs(str1,str2,len1+1,len2+1);
}
else{
return Math.max(lcs(str1,str2,len1+1,len2),lcs(str1,str2,len1,len2+1));
}
}

public int lcsDynamic(char str1[],char str2[]){

int temp[][] = new int[str1.length + 1][str2.length + 1];


int max = 0;
for(int i=1; i < temp.length; i++){
for(int j=1; j < temp[i].length; j++){
if(str1[i-1] == str2[j-1]) {
temp[i][j] = temp[i - 1][j - 1] + 1;
}
else
{
temp[i][j] = Math.max(temp[i][j-1],temp[i-1][j]);
}
if(temp[i][j] > max){
max = temp[i][j];
}
}
}
return max;

public static void main(String args[]){


LongestCommonSubsequence lcs = new LongestCommonSubsequence();
String str1 = "ABCDGHLQR";
String str2 = "AEDPHR";
int result = lcs.lcsDynamic(str1.toCharArray(), str2.toCharArray());
System.out.print(result);
}

}
package com.interview.dynamic;

/**
* http://en.wikipedia.org/wiki/Longest_common_substring_problem
*/
public class LongestCommonSubstring {

/**
* Dynamic way of calculating lcs
*/
public int longestCommonSubstring(char str1[], char str2[]){
int T[][] = new int[str1.length+1][str2.length+1];

int max = 0;
for(int i=1; i <= str1.length; i++){
for(int j=1; j <= str2.length; j++){
if(str1[i-1] == str2[j-1]){
T[i][j] = T[i-1][j-1] +1;
if(max < T[i][j]){
max = T[i][j];
}
}
}
}
return max;
}

/**
* Recursive way of calculating lcs
*/
public int longestCommonSubstringRec(char str1[], char str2[], int pos1, int
pos2, boolean checkEqual){
if(pos1 == -1 || pos2 == -1){
return 0;
}
if(checkEqual){
if(str1[pos1] == str2[pos2]){
return 1 + longestCommonSubstringRec(str1, str2, pos1-1, pos2-1,
true);
}else{
return 0;
}
}
int r1 = 0;
if(str1[pos1] == str2[pos2]){
r1 = 1 + longestCommonSubstringRec(str1, str2, pos1-1, pos2-1, true);
}
return Math.max(r1,Math.max(longestCommonSubstringRec(str1, str2, pos1-1,
pos2, false), longestCommonSubstringRec(str1, str2, pos1, pos2-1,false)));
}

public static void main(String args[]){


LongestCommonSubstring lcs = new LongestCommonSubstring();
char str1[] = "abcdef".toCharArray();
char str2[] = "zcdemf".toCharArray();
System.out.println(lcs.longestCommonSubstring(str1, str2));
System.out.println(lcs.longestCommonSubstringRec(str1, str2,str1.length-1,
str2.length-1,false));
}

}
package com.interview.dynamic;

/**
* http://www.geeksforgeeks.org/longest-even-length-substring-sum-first-second-half/
* Test cases
* Even length string
* odd length string
* 0 length string
*/
public class LongestEvenLengthSubstringOfEqualHalf {

public int findMaxLength(int input[]){


assert input != null;
int T[][] = new int[input.length][input.length];

for(int i=0; i < T.length; i++){


T[i][i] = input[i];
}
int max = 0;
for(int len = 2; len <= input.length; len++){
for(int i=0; i < input.length - len+1; i++){
int j = i + len-1;
//updating sum for each lenght
T[i][j] = T[i][j-1] + input[j];

if(len % 2 == 0){
int k = (i + j)/2;
if(T[i][k] == T[k+1][j]){
if(max < len){
max = len;
}
}
}
}
}
return max;
}

public static void main(String args[]){


int input[] = {1,5,3,8,0,2,14,9};
LongestEvenLengthSubstringOfEqualHalf lel = new
LongestEvenLengthSubstringOfEqualHalf();
System.out.println(lel.findMaxLength(input));
}
}
package com.interview.dynamic;

/**
* Date 03/10/2016
* @author Tushar Roy
*
* Given a 2D matrix find longest increasing path length in this matrix.
*
* Time complexity is O(n*m)
* Space complexity is O(n*m)
*
* Reference
* https://leetcode.com/problems/longest-increasing-path-in-a-matrix/
*/
public class LongestIncreasingPath {

public int longestIncreasingPath(int[][] matrix) {


if (matrix.length == 0 || matrix[0].length == 0) {
return 0;
}
int[][] distance = new int[matrix.length][matrix[0].length];
int max = 1;
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
int r = dfs(matrix, i, j, distance, Integer.MIN_VALUE);
if (r > max) {
max = r;
}
}
}
return max;
}

int dfs(int[][] matrix, int i, int j, int[][] distance, int prev) {


if (i < 0 || i >= matrix.length || j < 0 || j >= matrix[i].length) {
return 0;
}

if (matrix[i][j] <= prev) {


return 0;
}

if (distance[i][j] != 0) {
return distance[i][j];
}

int v1 = dfs(matrix, i - 1, j, distance, matrix[i][j]);


int v2 = dfs(matrix, i, j - 1, distance, matrix[i][j]);
int v3 = dfs(matrix, i + 1, j, distance, matrix[i][j]);
int v4 = dfs(matrix, i, j + 1, distance, matrix[i][j]);
distance[i][j] = 1 + Math.max(Math.max(v1, v2), Math.max(v3, v4));
return distance[i][j];
}

public static void main(String args[]) {


LongestIncreasingPath lip = new LongestIncreasingPath();
int[][] input = {{9, 9, 4},{6, 6, 8},{2, 1, 1}};
int[][] input1 = {{3, 4, 5}, {3, 2, 6}, {2, 2, 1}};
System.out.println(lip.longestIncreasingPath(input));
}
}
package com.interview.dynamic;

* Find a subsequence in given array in which the subsequence's elements are


* in sorted order, lowest to highest, and in which the subsequence is as long as
possible
*
* Solution :
* Dynamic Programming is used to solve this question. DP equation is
* if(arr[i] > arr[j]) { T[i] = max(T[i], T[j] + 1 }
*
* Time complexity is O(n^2).
* Space complexity is O(n)
*
/
*/
public class LongestIncreasingSubsequence {

/**
* DP way of solving LIS
*/
public int longestSubsequenceWithActualSolution(int arr[]){
int T[] = new int[arr.length];
int actualSolution[] = new int[arr.length];
for(int i=0; i < arr.length; i++){
T[i] = 1;
actualSolution[i] = i;
}

for(int i=1; i < arr.length; i++){


for(int j=0; j < i; j++){
if(arr[i] > arr[j]){
if(T[j] + 1 > T[i]){
T[i] = T[j] + 1;
//set the actualSolution to point to guy before me
actualSolution[i] = j;
}
}
}
}

//find the index of max number in T


int maxIndex = 0;
for(int i=0; i < T.length; i++){
if(T[i] > T[maxIndex]){
maxIndex = i;
}
}

//lets print the actual solution


int t = maxIndex;
int newT = maxIndex;
do{
t = newT;
System.out.print(arr[t] + " ");
newT = actualSolution[t];
}while(t != newT);
System.out.println();

return T[maxIndex];
}

/**
* Recursive way of solving LIS
*/
public int longestSubsequenceRecursive(int arr[]){
int maxLen = 0;
for(int i=0; i < arr.length-1; i++){
int len = longestSubsequenceRecursive(arr,i+1,arr[i]);
if(len > maxLen){
maxLen = len;
}
}
return maxLen + 1;
}

private int longestSubsequenceRecursive(int arr[], int pos, int lastNum){


if(pos == arr.length){
return 0;
}
int t1 = 0;
if(arr[pos] > lastNum){
t1 = 1 + longestSubsequenceRecursive(arr, pos+1, arr[pos]);
}
int t2 = longestSubsequenceRecursive(arr, pos+1, lastNum);
return Math.max(t1, t2);
}

public static void main(String args[]){


LongestIncreasingSubsequence lis = new LongestIncreasingSubsequence();
int arr[] = {23,10,22,5,33,8,9,21,50,41,60,80,99, 22,23,24,25,26,27};
int result = lis.longestSubsequenceWithActualSolution(arr);
int result1 = lis.longestSubsequenceRecursive(arr);
System.out.println(result);
System.out.println(result1);
}
}
package com.interview.dynamic;

* Given a string find longest palindromic subsequence in this string.


*
* Time complexity - O(n2)
* Space complexity - O(n2

public class LongestPalindromicSubsequence {

public int calculate1(char []str){


int T[][] = new int[str.length][str.length];
for(int i=0; i < str.length; i++){
T[i][i] = 1;
}
for(int l = 2; l <= str.length; l++){
for(int i = 0; i < str.length-l + 1; i++){
int j = i + l - 1;
if(l == 2 && str[i] == str[j]){
T[i][j] = 2;
}else if(str[i] == str[j]){
T[i][j] = T[i + 1][j-1] + 2;
}else{
T[i][j] = Math.max(T[i + 1][j], T[i][j - 1]);
}
}
}
return T[0][str.length-1];
}

public int calculateRecursive(char str[],int start,int len){


if(len == 1){
return 1;
}
if(len ==0){
return 0;
}
if(str[start] == str[start+len-1]){
return 2 + calculateRecursive(str,start+1,len-2);
}else{
return Math.max(calculateRecursive(str, start+1, len-1),
calculateRecursive(str, start, len-1));
}
}

public static void main(String args[]){


LongestPalindromicSubsequence lps = new LongestPalindromicSubsequence();
String str = "agbdba";
int r1 = lps.calculateRecursive(str.toCharArray(), 0, str.length());
int r2 = lps.calculate1(str.toCharArray());
System.out.print(r1 + " " + r2);
}

/**
* Date 02/11/2016
* @author Tushar Roy
*
* Wild car matching with ? and *
*
* Reference
* https://leetcode.com/problems/wildcard-matching/
*/
public class WildCardMatching {
public boolean isMatch(String s, String p) {
char[] str = s.toCharArray();
char[] pattern = p.toCharArray();

//replace multiple * with one *


//e.g a**b***c --> a*b*c
int writeIndex = 0;
boolean isFirst = true;
for ( int i = 0 ; i < pattern.length; i++) {
if (pattern[i] == '*') {
if (isFirst) {
pattern[writeIndex++] = pattern[i];
isFirst = false;
}
} else {
pattern[writeIndex++] = pattern[i];
isFirst = true;
}
}

boolean T[][] = new boolean[str.length + 1][writeIndex + 1];

if (writeIndex > 0 && pattern[0] == '*') {


T[0][1] = true;
}

T[0][0] = true;

for (int i = 1; i < T.length; i++) {


for (int j = 1; j < T[0].length; j++) {
if (pattern[j-1] == '?' || str[i-1] == pattern[j-1]) {
T[i][j] = T[i-1][j-1];
} else if (pattern[j-1] == '*'){
T[i][j] = T[i-1][j] || T[i][j-1];
}
}
}

return T[str.length][writeIndex];
}

/**
* Recursive and slow version of wild card matching.
*/
public boolean isMatchRecursive(String s, String p) {
return isMatchRecursiveUtil(s.toCharArray(), p.toCharArray(),
0, 0);
}

private boolean isMatchRecursiveUtil(char[] text, char[] pattern,


int pos1, int pos2) {
if (pos2 == pattern.length) {
return text.length == pos1;
}

if (pattern[pos2] != '*') {
if (pos1 < text.length && (text[pos1] == pattern[pos2]) ||
pattern[pos2] == '?') {
return isMatchRecursiveUtil(text, pattern, pos1 + 1,
pos2 + 1);
} else {
return false;
}
} else {
//if we have a***b then skip to the last *
while (pos2 < pattern.length - 1 && pattern[pos2 + 1] ==
'*') {
pos2++;
}
pos1--;
while (pos1 < text.length) {
if (isMatchRecursiveUtil(text, pattern, pos1 + 1, pos2
+ 1)) {
return true;
}
pos1++;
}
return false;
}
}

public static void main(String args[]) {


WildCardMatching wcm = new WildCardMatching();
System.out.println(wcm.isMatch("xbylmz", "x?y*z"));
}
}

package com.interview.dynamic;

import java.util.Arrays;
import java.util.Comparator;

class Job{
int start;
int end;
int profit;
Job(int start,int end,int profit){
this.start= start;
this.end = end;
this.profit= profit;
}
}

class FinishTimeComparator implements Comparator<Job>{

@Override
public int compare(Job arg0, Job arg1) {
if(arg0.end <= arg1.end){
return -1;
}else{
return 1;
}
}

/**
*
http://www.cs.princeton.edu/courses/archive/spr05/cos423/lectures/06dy
namic-programming.pdf
* Given set of jobs with start and end interval and profit, how to
maximize profit such that
* jobs in subset do not overlap.
*/

public class WeightedJobSchedulingMaximumProfit {

/**
* Sort the jobs by finish time.
* For every job find the first job which does not overlap with
this job
* and see if this job profit plus profit till last non
overlapping job is greater
* than profit till last job.
* @param jobs
* @return
*/
public int maximum(Job[] jobs){
int T[] = new int[jobs.length];
FinishTimeComparator comparator = new FinishTimeComparator();
Arrays.sort(jobs, comparator);

T[0] = jobs[0].profit;
for(int i=1; i < jobs.length; i++){
T[i] = Math.max(jobs[i].profit, T[i-1]);
for(int j=i-1; j >=0; j--){
if(jobs[j].end <= jobs[i].start){
T[i] = Math.max(T[i], jobs[i].profit + T[j]);
break;
}
}
}
int maxVal = Integer.MIN_VALUE;
for (int val : T) {
if (maxVal < val) {
maxVal = val;
}
}
return maxVal;
}

public static void main(String args[]){


Job jobs[] = new Job[6];
jobs[0] = new Job(1,3,5);
jobs[1] = new Job(2,5,6);
jobs[2] = new Job(4,6,5);
jobs[3] = new Job(6,7,4);
jobs[4] = new Job(5,8,11);
jobs[5] = new Job(7,9,2);
WeightedJobSchedulingMaximumProfit mp = new
WeightedJobSchedulingMaximumProfit();
System.out.println(mp.maximum(jobs));
}
}

package com.interview.dynamic;

import java.util.PriorityQueue;

/**
* Date 03/08/2016
* @author Tushar Roy
*
* Find nth ugly number.
*
* https://leetcode.com/problems/ugly-number-ii/
* https://leetcode.com/problems/super-ugly-number/
* http://www.geeksforgeeks.org/ugly-numbers/
*/

public class UglyNumbers {

static class Node implements Comparable<Node> {


int inputIndex;
int index;
int val;
Node (int inputIndex, int index, int val) {
this.index = index;
this.val = val;
this.inputIndex = inputIndex;
}

@Override
public int compareTo(Node other) {
return this.val - other.val;
}
}

public int nthSuperUglyNumber1(int n, int[] primes) {

PriorityQueue<Node> pq = new PriorityQueue<>();


for (int i = 0; i < primes.length; i++) {
pq.offer(new Node(i, 0, primes[i]));
}
int[] val = new int[n];
val[0] = 1;
for (int i = 1; i < n; ) {
Node node = pq.poll();
if (val[i-1] != node.val) {
val[i] = node.val;
i++;
}
node.index = node.index + 1;
node.val = primes[node.inputIndex]*val[node.index];
pq.offer(node);
}
return val[n - 1];
}

int ugly(int n){


int arr[] = new int[n];
int count = 1;
arr[0] = 1;
int i2 = 0;
int i3 = 0;
int i5 = 0;
while(count < n){
int minNumber = min(arr[i2] * 2, arr[i3] * 3, arr[i5] *
5);
if(minNumber == arr[i2]*2){
i2++;
}
if(minNumber == arr[i3]*3){
i3++;
}
if(minNumber == arr[i5]*5){
i5++;
}
arr[count++] = minNumber;
}

return arr[n-1];
}

private int min(int a,int b, int c){


int l = Math.min(a, b);
return Math.min(l, c);
}

public static void main(String args[]) {


UglyNumbers ugly = new UglyNumbers();
int result = ugly.ugly(150);
System.out.println(result);
int[] primes = {2, 3, 7, 11};
System.out.print(ugly.nthSuperUglyNumber1(17, primes));
}

package com.interview.dynamic;

/**
*
* http://www.geeksforgeeks.org/check-whether-a-given-string-is-an-
interleaving-of-two-other-given-strings-set-2/
*/
public class TwoStringInterleavingToFormThird {

public boolean isInterleavedRecursive(char str1[], char str2[],


char str3[],int pos1, int pos2, int pos3){
if(pos1 == str1.length && pos2 == str2.length && pos3 ==
str3.length){
return true;
}

if(pos3 == str3.length){
return false;
}

return (pos1 < str1.length && str1[pos1] == str3[pos3] &&


isInterleavedRecursive(str1, str2, str3, pos1+1, pos2, pos3+1))
|| (pos2 < str2.length && str2[pos2] == str3[pos3] &&
isInterleavedRecursive(str1, str2, str3, pos1, pos2+1, pos3+1));

}
public boolean isInterleaved(char str1[], char str2[], char
str3[]){
boolean T[][] = new boolean[str1.length +1][str2.length +1];

if(str1.length + str2.length != str3.length){


return false;
}

for(int i=0; i < T.length; i++){


for(int j=0; j < T[i].length; j++){
int l = i + j -1;
if(i == 0 && j == 0){
T[i][j] = true;
}
else if(i == 0){
if(str3[l] == str2[j-1]){
T[i][j] = T[i][j-1];
}
}
else if(j == 0){
if(str1[i-1] == str3[l]){
T[i][j] = T[i-1][j];
}
}
else{
T[i][j] = (str1[i-1] == str3[l] ? T[i-1][j] :
false) || (str2[j-1] == str3[l] ? T[i][j-1] : false);
}
}
}
return T[str1.length][str2.length];
}

public static void main(String args[]){


String str1 = "XXYM";
String str2 = "XXZT";
String str3 = "XXXZXYTM";
TwoStringInterleavingToFormThird sti = new
TwoStringInterleavingToFormThird();
System.out.println(sti.isInterleaved(str1.toCharArray(),
str2.toCharArray(), str3.toCharArray()));
}

package com.interview.dynamic;

/**
* Date 05/07/2015
* @author tusroy
*
* Video link - https://youtu.be/RORuwHiblPc
*
* Given a sequence of words, and a limit on the number of characters
that can be put
* in one line (line width). Put line breaks in the given sequence
such that the
* lines are printed neatly
*
* Solution:
* Badness - We define badness has square of empty spaces in every
line. So 2 empty space
* on one line gets penalized as 4 (2^2) while 1 each empty space on 2
lines gets
* penalized as 2(1 + 1). So we prefer 1 empty space on different
lines over 2 empty space on
* one line.
*
* For every range i,j(words from i to j) find the cost of putting
them on one line. If words
* from i to j cannot fit in one line cost will be infinite. Cost is
calculated as square of
* empty space left in line after fitting words from i to j.
*
* Then apply this formula to get places where words need to be going
on new line.
* minCost[i] = minCost[j] + cost[i][j-1]
* Above formula will try every value of j from i to len and see which
one gives minimum
* cost to split words from i to len.
*
* Space complexity is O(n^2)
* Time complexity is O(n^2)
*
* References:
* http://www.geeksforgeeks.org/dynamic-programming-set-18-word-wrap/
*/
public class TextJustification {

public String justify(String words[], int width) {

int cost[][] = new int[words.length][words.length];

//next 2 for loop is used to calculate cost of putting words


from
//i to j in one line. If words don't fit in one line then we
put
//Integer.MAX_VALUE there.
for(int i=0 ; i < words.length; i++){
cost[i][i] = width - words[i].length();
for(int j=i+1; j < words.length; j++){
cost[i][j] = cost[i][j-1] - words[j].length() - 1;
}
}

for(int i=0; i < words.length; i++){


for(int j=i; j < words.length; j++){
if(cost[i][j] < 0){
cost[i][j] = Integer.MAX_VALUE;
}else{
cost[i][j] = (int)Math.pow(cost[i][j], 2);
}
}
}

//minCost from i to len is found by trying


//j between i to len and checking which
//one has min value
int minCost[] = new int[words.length];
int result[] = new int[words.length];
for(int i = words.length-1; i >= 0 ; i--){
minCost[i] = cost[i][words.length-1];
result[i] = words.length;
for(int j=words.length-1; j > i; j--){
if(cost[i][j-1] == Integer.MAX_VALUE){
continue;
}
if(minCost[i] > minCost[j] + cost[i][j-1]){
minCost[i] = minCost[j] + cost[i][j-1];
result[i] = j;
}
}
}
int i = 0;
int j;

System.out.println("Minimum cost is " + minCost[0]);


System.out.println("\n");
//finally put all words with new line added in
//string buffer and print it.
StringBuilder builder = new StringBuilder();
do{
j = result[i];
for(int k=i; k < j; k++){
builder.append(words[k] + " ");
}
builder.append("\n");
i = j;
}while(j < words.length);

return builder.toString();
}

public static void main(String args[]){


String words1[] = {"Tushar","likes","to","write","code","at",
"free", "time"};
TextJustification awl = new TextJustification();
System.out.println(awl.justify(words1, 12));
}
}

package com.interview.dynamic;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
* Date 01/06/2016
* @author Tushar Roy
* Let there be a binary operation for 3 symbols a, b, c and result of
these binary operation given in a table.
* Given an expression of these 3 symbols and a final result, tell if
this expression can be parenthesize in certain
* way to produce the final result.
*
* Time complexity is O(n^4)
* Space complexity is O(n^3)
*/
public class SymbolExpressionEvaluation {

public boolean evaluateExpression(char input[][], Map<Character,


Integer> index, char[] expression, char result) {
Holder[][] T = new
Holder[expression.length][expression.length];
for (int i = 0; i < T.length; i++) {
for (int j = 0; j < T.length; j++) {
T[i][j] = new Holder();
}
}

for (int i = 0; i < expression.length; i++) {


T[i][i].add(expression[i]);
}

for (int l = 2; l <= T.length; l++) {


for (int i = 0; i <= T.length - l; i++) {
int j = i + l - 1;
for (int k = i; k < j; k++) {
for (char ch : T[i][k].values()) {
for (char ch1: T[k+1][j].values()) {

T[i][j].add(input[index.get(ch)][index.get(ch1)]);
}
}
}
}
}

for (char ch : T[0][T.length-1].values()) {


if ( result == ch) {
return true;
}
}
return false;
}

public static void main(String args[]) {


Map<Character, Integer> index = new HashMap<>();
index.put('a', 0);
index.put('b', 1);
index.put('c', 2);

char input[][] = {{'b', 'b', 'a'}, {'c', 'b', 'a'}, {'a', 'c',
'c'}};
SymbolExpressionEvaluation sbe = new
SymbolExpressionEvaluation();
System.out.println(sbe.evaluateExpression(input, index,
"bbbbac".toCharArray(), 'a'));
}

class Holder {
private Set<Character> valueHolder = new HashSet<>();
void add(Character ch) {
valueHolder.add(ch);
}
Set<Character> values() {
return valueHolder;
}
}

package com.interview.dynamic;

/**
* Date 09/15/2014
* @author tusroy
*
* Find maximum subsquare in a matrix made up of Xs and Os such that
all four sides of subsquare are Xs. It does not matter what is inside
* the subsquare. All 4 sides should be made up entirely of Xs
*
* e.g
* 0 0 0 0 0 X 0,0 0,0 0,0 0,0 0,0 1,1
* 0 X 0 X X X 0,0 1,1 0,0 1,1 1,2 2,3
* 0 X 0 X 0 X 0,0 2,1 0,0 2,1 0,0 3,1
* 0 X X X X X 0,0 3,1 1,2 3,3 1,4 4,5
* 0 0 0 0 0 0 0,0 0,0 0,0 0,0 0,0 0,0
*
* Output of above program should be 3
*
* Solution
* Have another matrix which is capable of holding 2 values hori and
ver.
* Ver stores how far vertically you can see Xs. Hori stores how far
horizontally you can see Xs.
* Once this matrix is build look for biggest subsquare by getting min
of hori and ver at each point and checking
* if subsquare can be formed from value min to 1.
*
* Test cases:
* Matrix entirely made up of Xs
* Matrix entirely made up of Os
* Matrix with Xs and Os but maximum subsquare is length 1
*/
public class SubsquareSurrounedByXs {

class Cell{
int ver;
int hori;
}
public int findSubSquare(char input[][]){
Cell T[][] = new Cell[input.length][input[0].length];
for(int i=0; i < T.length; i++){
for(int j=0; j < T[0].length; j++){
T[i][j] = new Cell();
}
}

for(int i=0; i < input.length; i++){


for(int j=0; j < input[0].length; j++){
if(input[i][j] == 'X'){
if(i == 0 && j == 0){
T[i][j].hori = 1;
T[i][j].ver = 1;
}
else if(i == 0){
T[i][j].hori = T[i][j-1].hori + 1;
T[i][j].ver = 1;
}else if(j == 0){
T[i][j].ver = T[i-1][j].ver +1;
T[i][j].hori = 1;
}else{
T[i][j].hori = T[i][j-1].hori +1;
T[i][j].ver = T[i-1][j].ver + 1;
}
}
}
}
for(int i=0; i < T.length; i++){
for(int j=0; j < T[0].length; j++){
System.out.print(T[i][j].ver + "," + T[i][j].hori+ "
");
}
System.out.println();
}

//start iterating from bottom right corner and find min of


hori or ver at every cell.
//If this is greater than 1 then see if you can find a number
between this min and 1
//such that on left's ver and top's hori is greater greater
than or equal to k.
int max = 1;
for(int i=T.length -1; i >=0 ; i--){
for(int j= T[0].length-1 ; j >=0; j--){
if(T[i][j].ver == 0 || T[i][j].ver == 1 ||
T[i][j].hori ==1 ){
continue;
}
int min = Math.min(T[i][j].ver, T[i][j].hori);
int k = 0;
for(k=min; k > 1; k--){
if(T[i][j-k+1].ver >= k && T[i-k+1][j].hori >= k){
break;
}
}
if(max < k){
max = k;
}
}
}

return max;
}

public static void main(String args[]){


char[][] input = {{'X','O','O','O','O','O'},
{'O','O','O','O','O','O'},
{'X','X','X','X','O','O'},
{'X','X','X','X','X','O'},
{'X','O','O','X','X','O'},
{'X','O','X','X','X','O'}};

char [][] input1 = {{'O', 'O', 'O', 'O', 'O', 'X'},


{'O', 'X', 'O', 'X', 'X', 'X'},
{'O', 'X', 'O', 'X', 'O', 'X'},
{'O', 'X', 'X', 'X', 'X', 'X'},
{'O', 'O', 'O', 'O', 'O', 'O'},
};

char [][] input2 = {{'O', 'O', 'X', 'O', 'X'},


{'O', 'X', 'X', 'O', 'X'},
{'O', 'X', 'O', 'X', 'X'},
{'X', 'X', 'X', 'X', 'X'},
{'O', 'X', 'X', 'X', 'O'},
};

SubsquareSurrounedByXs ss = new SubsquareSurrounedByXs();


System.out.println(ss.findSubSquare(input));
System.out.println(ss.findSubSquare(input1));
System.out.println(ss.findSubSquare(input2));
}

package com.interview.dynamic;
/*
* Date 09/23/2014
* @author Tushar Roy
*
* Given an array of non negative numbers and a total, is there subset
of numbers in this array which adds up
* to given total. Another variation is given an array is it possible
to split it up into 2 equal
* sum partitions. Partition need not be equal sized. Just equal sum.
*
* Time complexity - O(input.size * total_sum)
* Space complexity - O(input.size*total_sum)
*
* Youtube video - https://youtu.be/s6FhG--P7z0
*/
public class SubsetSum {

public boolean subsetSum(int input[], int total) {

boolean T[][] = new boolean[input.length + 1][total + 1];


for (int i = 0; i <= input.length; i++) {
T[i][0] = true;
}

for (int i = 1; i <= input.length; i++) {


for (int j = 1; j <= total; j++) {
if (j - input[i - 1] >= 0) {
T[i][j] = T[i - 1][j] || T[i - 1][j - input[i -
1]];
} else {
T[i][j] = T[i-1][j];
}
}
}
return T[input.length][total];

public boolean partition(int arr[]) {


int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}

if (sum % 2 != 0) {
return false;
}
sum = sum / 2;
boolean[][] T = new boolean[arr.length + 1][sum + 1];

for (int i = 0; i <= arr.length; i++) {


T[i][0] = true;
}

for (int i = 1; i <= arr.length; i++) {


for (int j = 1; j <= sum; j++) {
if (j - arr[i - 1] >= 0) {
T[i][j] = T[i - 1][j - arr[i - 1]] || T[i - 1][j];
} else {
T[i][j] = T[i-1][j];
}
}
}
return T[arr.length][sum];
}

public static void main(String args[]) {


SubsetSum ss = new SubsetSum();
int arr[] = {1, 3, 5, 5, 2, 1, 1, 6};
System.out.println(ss.partition(arr));

int arr1[] = {2, 3, 7, 8};


System.out.print(ss.subsetSum(arr1, 11));

}
}

package com.interview.dynamic;

/**
* Date 07/31/2014
* @author tusroy
*
* Write a program to find maximum sum rectangle in give 2D matrix.
* Assume there is at least one positive number in the 2D matrix.
*
* Solution:
* Keep temp array with size as number of rows. Start left and right
from 0
* and keep adding values for each row and maintain them in this temp
array.
* Run Kadane's algorithm to find max sum subarray in temp. Now
increment right by
* 1. When right reaches last column reset right to 1 and left to 1.
*
* Space complexity of this algorithm is O(row)
* Time complexity of this algorithm is O(row*col*col)
*
* References
* http://www.geeksforgeeks.org/dynamic-programming-set-27-max-sum-
rectangle-in-a-2d-matrix/
*/
public class SubRectangularMatrixWithMaximumSum {

class Result{
int maxSum;
int leftBound;
int rightBound;
int upBound;
int lowBound;
@Override
public String toString() {
return "Result [maxSum=" + maxSum + ", leftBound=" +
leftBound
+ ", rightBound=" + rightBound + ", upBound=" +
upBound
+ ", lowBound=" + lowBound + "]";
}

public Result maxSum(int input[][]){


int rows = input.length;
int cols = input[0].length;
int temp[] = new int[rows];
Result result = new Result();
for(int left = 0; left < cols ; left++){
for(int i=0; i < rows; i++){
temp[i] = 0;
}
for(int right = left; right < cols; right++){
for(int i=0; i < rows; i++){
temp[i] += input[i][right];
}
KadaneResult kadaneResult = kadane(temp);
if(kadaneResult.maxSum > result.maxSum){
result.maxSum = kadaneResult.maxSum;
result.leftBound = left;
result.rightBound = right;
result.upBound = kadaneResult.start;
result.lowBound = kadaneResult.end;
}
}
}
return result;
}

class KadaneResult{
int maxSum;
int start;
int end;
public KadaneResult(int maxSum, int start, int end) {
this.maxSum = maxSum;
this.start = start;
this.end = end;
}
}

private KadaneResult kadane(int arr[]){


int max = 0;
int maxStart = -1;
int maxEnd = -1;
int currentStart = 0;
int maxSoFar = 0;
for(int i=0; i < arr.length; i++){
maxSoFar += arr[i];
if(maxSoFar < 0){
maxSoFar = 0;
currentStart = i+1;
}
if(max < maxSoFar){
maxStart = currentStart;
maxEnd = i;
max = maxSoFar;
}
}
return new KadaneResult(max, maxStart, maxEnd);
}

public static void main(String args[]){


int input[][] = {{ 2, 1, -3, -4, 5},
{ 0, 6, 3, 4, 1},
{ 2, -2, -1, 4, -5},
{-3, 3, 1, 0, 3}};
SubRectangularMatrixWithMaximumSum saw = new
SubRectangularMatrixWithMaximumSum();
System.out.println(saw.maxSum(input));
}
}

package com.interview.dynamic;

import java.util.Deque;
import java.util.LinkedList;

/**
* Date 12/22/2015
* @author Tushar Roy
*
* Given stockc prices for certain days and at most k transactions how
to buy and sell
* to maximize profit.
*
* Time complexity - O(number of transactions * number of days)
* Space complexity - O(number of transcations * number of days)
*
* https://leetcode.com/discuss/15153/a-clean-dp-solution-which-
generalizes-to-k-transactions
*/
public class StockBuySellKTransactions {

/**
* This is faster method which does optimization on slower method
* Time complexity here is O(K * number of days)
*
* Formula is
* T[i][j] = max(T[i][j-1], prices[j] + maxDiff)
* maxDiff = max(maxDiff, T[i-1][j] - prices[j])
*/
public int maxProfit(int prices[], int K) {
if (K == 0 || prices.length == 0) {
return 0;
}
int T[][] = new int[K+1][prices.length];

for (int i = 1; i < T.length; i++) {


int maxDiff = -prices[0];
for (int j = 1; j < T[0].length; j++) {
T[i][j] = Math.max(T[i][j-1], prices[j] + maxDiff);
maxDiff = Math.max(maxDiff, T[i-1][j] - prices[j]);
}
}
printActualSolution(T, prices);
return T[K][prices.length-1];
}

/**
* This is slow method but easier to understand.
* Time complexity is O(k * number of days ^ 2)
* T[i][j] = max(T[i][j-1], max(prices[j] - prices[m] + T[i-
1][m])) where m is 0...j-1
*/
public int maxProfitSlowSolution(int prices[], int K) {
if (K == 0 || prices.length == 0) {
return 0;
}
int T[][] = new int[K+1][prices.length];

for (int i = 1; i < T.length; i++) {


for (int j = 1; j < T[0].length; j++) {
int maxVal = 0;
for (int m = 0; m < j; m++) {
maxVal = Math.max(maxVal, prices[j] - prices[m] +
T[i-1][m]);
}
T[i][j] = Math.max(T[i][j-1], maxVal);
}
}
printActualSolution(T, prices);
return T[K][prices.length - 1];
}

public void printActualSolution(int T[][], int prices[]) {


int i = T.length - 1;
int j = T[0].length - 1;

Deque<Integer> stack = new LinkedList<>();


while(true) {
if(i == 0 || j == 0) {
break;
}
if (T[i][j] == T[i][j-1]) {
j = j - 1;
} else {
stack.addFirst(j);
int maxDiff = T[i][j] - prices[j];
for (int k = j-1; k >= 0; k--) {
if (T[i-1][k] - prices[k] == maxDiff) {
i = i - 1;
j = k;
stack.addFirst(j);
break;
}
}
}
}

while(!stack.isEmpty()) {
System.out.println("Buy at price " +
prices[stack.pollFirst()]);
System.out.println("Sell at price " +
prices[stack.pollFirst()]);
}

public static void main(String args[]) {


StockBuySellKTransactions sbt = new
StockBuySellKTransactions();
int prices[] = {2, 5, 7, 1, 4, 3, 1, 3};

System.out.println("Max profit fast solution " +


sbt.maxProfit(prices, 3));
System.out.println("Max profit slow solution " +
sbt.maxProfitSlowSolution(prices, 3));
}
}

package com.interview.dynamic;

import java.util.HashMap;
import java.util.Map;

/**
* Read question at https://leetcode.com/problems/scramble-string/
*/
public class ScrambledString {

/**
* Index for memoization.
*/
private static class Index {
int start1;
int end1;
int start2;

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Index index = (Index) o;

if (start1 != index.start1) return false;


if (end1 != index.end1) return false;
if (start2 != index.start2) return false;
return end2 == index.end2;

@Override
public int hashCode() {
int result = start1;
result = 31 * result + end1;
result = 31 * result + start2;
result = 31 * result + end2;
return result;
}

int end2;
}

boolean isScrambled(char input1[], char input2[], int start1, int


end1, int start2, int end2, Map<Index, Boolean> memMap) {

//return false conditions


if(start1 > end1 || start2 > end2) {
return false;
}
if(end1 - start1 != end2 - start2) {
return false;
}

Index index = new Index();


index.start1 = start1;
index.end1 = end1;
index.start2 = start2;
index.end2 = end2;

//if we have already calculated value for index then lets use
it instead of recalculating again.
if(memMap.containsKey(index)) {
return memMap.get(index);
}

//if both input from their respective start to end are same
then return true.
boolean isSame = true;
for(int i= start1, j = start2; i <= end1 && j <= end2; i++,
j++) {
if(input1[i] != input2[j]) {
isSame = false;
break;
}
}

if(isSame) {
memMap.put(index, true);
return true;
}

//check if both input from their respective start to end have


same characters. If not then return false.
Map<Character, Integer> countMap = new HashMap<>();
for(int i= start1; i <= end1; i++) {
countMap.compute(input1[i], (ch, val) -> {
if(val == null) {
return 1;
} else {
return val + 1;
}
});
}

for(int i= start2; i <= end2; i++) {


countMap.compute(input2[i], (ch, val) -> {
if(val == null) {
return -1;
} else {
return val - 1;
}
});
}

//all values in map should have value 0 otherwise there is


character mismatch. Return false in that case.
long nonZeroCount = countMap.values().stream().filter(val ->
val !=0 ).count();
if(nonZeroCount > 0) {
memMap.put(index, false);
return false;
}

//for values from input range try splitting into 2 and check
recursively if they match or not.
for(int len = 0; len < end1 - start1; len++) {
//e.g great gtear so match g ,g and reat, tear
if(isScrambled(input1, input2, start1, start1 + len,
start2, start2 + len, memMap) &&
isScrambled(input1, input2, start1 + len +1, end1,
start2 + len + 1, end2, memMap)) {
memMap.put(index, true);
return true;
}
//e.g great reatg so match g,g and reat,reat
if(isScrambled(input1, input2, start1, start1 + len, end2
- len, end2, memMap) &&
isScrambled(input1, input2, start1 + len +1, end1,
start2, end2 - len -1, memMap)) {
memMap.put(index, true);
return true;
}
}
memMap.put(index, false);
return false;
}

public static void main(String args[]) {


ScrambledString ss = new ScrambledString();
String str1 = "great";
String str2 = "rgtae";
Map<Index, Boolean> memMap = new HashMap<>();
boolean result = ss.isScrambled(str1.toCharArray(),
str2.toCharArray(), 0, str1.length() - 1, 0, str2.length() -1,
memMap);
System.out.println(result);
}

package com.interview.dynamic;

/**
* http://www.geeksforgeeks.org/remove-minimum-elements-either-side-
2min-max/
*/
public class RemoveFromEndToMake2IntoMinGreaterThanMax {

public int removeFromEnd(int input[]){


return removeFromEnd(input,0,input.length-1);
}

private int removeFromEnd(int input[],int low,int high){


if(low > high){
return input.length;
}
int min = min(input,low,high);
int max = max(input,low,high);
if(2*min > max){
return 0;
}

return Math.min(removeFromEnd(input,low,high-1),
removeFromEnd(input,low+1,high)) +1;
}

private int min(int input[],int low,int high){


int min = Integer.MAX_VALUE;
for(int i=low; i <=high; i++){
if(min > input[i]){
min = input[i];
}
}
return min;
}
private int max(int input[],int low,int high){
int max = Integer.MIN_VALUE;
for(int i=low; i <=high; i++){
if(max < input[i]){
max = input[i];
}
}
return max;
}

public int removeFromEndDynamic(int input[]){


int T[][] = new int[input.length][input.length];
for(int l=1; l <= input.length; l++){
for(int i=0, j = i + l-1; i < input.length-l+1; i++,j++){
int min = min(input,i,j);
int max = max(input,i,j);
if(2*min > max){
T[i][j] = 0;
}else{
T[i][j] = Math.min(T[i+1][j] , T[i][j-1]) +1;
}
}
}
return T[0][input.length-1];
}
public static void main(String args[]){
int input[] = {5,1,3,1,3,8,3};
RemoveFromEndToMake2IntoMinGreaterThanMax rme = new
RemoveFromEndToMake2IntoMinGreaterThanMax();
System.out.println(rme.removeFromEnd(input));
System.out.println(rme.removeFromEndDynamic(input));
}
}

package com.interview.dynamic;
/**
* Date 06/24/2015
* @author Tushar Roy
*
* Write a program to perform regex matching with * an .
*
* References : http://leetcode.com/2011/09/regular-expression-
matching.html
*/
public class RegexMatching {

public boolean matchRegexRecursive(char[] str, char[] pattern){


return matchRegexRecursive(str,pattern,0,0);
}

private boolean matchRegexRecursive(char text[], char pattern[],


int pos1, int pos2){
//if pos2 has reached end of pattern means pos2 should also
reach end of text for match
//to happen
if(pos2 == pattern.length) {
return pos1 == text.length;
}

//if next character is not * means either current value at


pattern and text should be same
//or current value at pattern should be . in which case you
can skip one character of text
if(pos2 == pattern.length - 1 || pattern[pos2+1] != '*') {
return (pos1 < text.length && (text[pos1] == pattern[pos2]
|| pattern[pos2] == '.')) && matchRegexRecursive(text, pattern,
pos1+1, pos2+1);
}

//if we have case like abc and ad*bc so here we totally skip
d*
if(matchRegexRecursive(text, pattern, pos1, pos2+2)){
return true;
}

//For case like abbc and ab*c match first b with b* and then
next b to c. If that does not work out
//then try next b with b* and then c with c and so on.
//if pattern current val is . then skip one character at time
from text till we either reach end of text
//or a match is found
while(pos1 < text.length && (text[pos1] == pattern[pos2] ||
pattern[pos2] == '.')){
if( matchRegexRecursive(text, pattern, pos1+1, pos2+2)){
return true;
}
pos1++;
}
return false;
}

/**
* Dynamic programming technique for regex matching.
*/
public boolean matchRegex(char[] text, char[] pattern) {
boolean T[][] = new boolean[text.length + 1][pattern.length +
1];

T[0][0] = true;
//Deals with patterns like a* or a*b* or a*b*c*
for (int i = 1; i < T[0].length; i++) {
if (pattern[i-1] == '*') {
T[0][i] = T[0][i - 2];
}
}

for (int i = 1; i < T.length; i++) {


for (int j = 1; j < T[0].length; j++) {
if (pattern[j - 1] == '.' || pattern[j - 1] == text[i
- 1]) {
T[i][j] = T[i-1][j-1];
} else if (pattern[j - 1] == '*') {
T[i][j] = T[i][j - 2];
if (pattern[j-2] == '.' || pattern[j - 2] ==
text[i - 1]) {
T[i][j] = T[i][j] | T[i - 1][j];
}
} else {
T[i][j] = false;
}
}
}
return T[text.length][pattern.length];
}

public static void main(String args[]){


RegexMatching rm = new RegexMatching();

System.out.println(rm.matchRegexRecursive("Tushar".toCharArray(),"Tush
ar".toCharArray()));

System.out.println(rm.matchRegexRecursive("Tusha".toCharArray(),"Tusha
r*a*b*".toCharArray()));

System.out.println(rm.matchRegexRecursive("".toCharArray(),"a*b*".toCh
arArray()));

System.out.println(rm.matchRegexRecursive("abbbbccc".toCharArray(),"a*
ab*bbbbc*".toCharArray()));

System.out.println(rm.matchRegexRecursive("abbbbccc".toCharArray(),"aa
*bbb*bbbc*".toCharArray()));

System.out.println(rm.matchRegexRecursive("abbbbccc".toCharArray(),".*
bcc".toCharArray()));

System.out.println(rm.matchRegexRecursive("abbbbccc".toCharArray(),".*
bcc*".toCharArray()));

System.out.println(rm.matchRegexRecursive("abbbbccc".toCharArray(),".*
bcc*".toCharArray()));

System.out.println(rm.matchRegexRecursive("aaa".toCharArray(),"ab*a*c*
a".toCharArray()));

System.out.println(rm.matchRegex("aa".toCharArray(),
"a*".toCharArray()));
}
}

package com.interview.dynamic;

import java.util.HashMap;
import java.util.Map;

/**
* Given the mobile numeric keypad. You can only press buttons that
are
* up,left,right or down to the current button.You are not allowed to
press
* bottom row corner buttons (i.e. * and # ).Given a N find out the
number of
* numbers possible of given length.
*
* The idea is that to calculate for i all you have to do is add up i-
1 values of all the neighbors.
* e.g for i =2 and at 0 you need find i=1s of all neighbors including
0 and add them up.
*/
public class PhoneDialNumberOfCombinationOfSizeK {

/**
* -1 in the input means don't use that position
*
* @param k
* @param input
* @return
*/
public int numberOfCombination(int k, int input[][]) {
if (input == null || input.length == 0) {
throw new IllegalArgumentException();
}
Map<Integer, Integer> t = new HashMap<Integer, Integer>();
Map<Integer, Integer> t1 = new HashMap<Integer, Integer>();

for (int i = 0; i < input.length; i++) {


for (int j = 0; j < input[i].length; j++) {
if (input[i][j] < 0) {
continue;
}
t1.put(input[i][j], 1);
}
}

for (int x = 1; x < k; x++) {


for (int i = 0; i < input.length; i++) {
for (int j = 0; j < input[i].length; j++) {
if (input[i][j] < 0) {
continue;
}
findNeighborsAndPopulateMap(i, j, input, t,
t1);
}
}
copyMap(t, t1);
t.clear();
}
int count = 0;
for (int i : t1.keySet()) {
count += t1.get(i);
}
return count;
}

private void copyMap(Map<Integer, Integer> t, Map<Integer,


Integer> t1) {
for (Integer i : t.keySet()) {
int c = t.get(i);
t1.put(i, c);
}
}

private void findNeighborsAndPopulateMap(int x, int y, int


input[][],
Map<Integer, Integer> t, Map<Integer, Integer> t1) {
updateMap(input, x, y, x - 1, y, t, t1);
updateMap(input, x, y, x, y - 1, t, t1);
updateMap(input, x, y, x, y, t, t1);
updateMap(input, x, y, x, y + 1, t, t1);
updateMap(input, x, y, x + 1, y, t, t1);
}

private void updateMap(int input[][], int x, int y, int i, int j,


Map<Integer, Integer> t, Map<Integer, Integer> t1) {
if (i < 0 || i >= input.length || j < 0 || j >=
input[x].length
|| input[i][j] < 0) {
return;
}
Integer c = t.get(input[x][y]);
if (c == null) {
c = 0;
}
c += t1.get(input[i][j]);
t.put(input[x][y], c);
}

public static void main(String args[]) {


int input[][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }, {
-1, 0, -1 } };
PhoneDialNumberOfCombinationOfSizeK pdn = new
PhoneDialNumberOfCombinationOfSizeK();
System.out.println(pdn.numberOfCombination(3, input));
}

package com.interview.dynamic;

import java.util.*;

/**
* Date 04/03/2016
* @author Tushar Roy
*
* Partitioning the string into palindromes.
*
* https://leetcode.com/problems/palindrome-partitioning/
* https://leetcode.com/problems/palindrome-partitioning-ii/
*/
public class PalindromePartition {

/*
* Given a string s, partition s such that every substring of the
partition is a palindrome.
* Return the minimum cuts needed for a palindrome partitioning of
s.
* https://leetcode.com/problems/palindrome-partitioning-ii/
*/
public int minCut(String str){
if (str.length() == 0) {
return 0;
}

int[] cut = new int[str.length()];


boolean isPal[][] = new boolean[str.length()][str.length()];
for (int i = 1; i < str.length(); i++) {
int min = i;
for (int j = 0; j <= i; j++) {
if (str.charAt(i) == str.charAt(j) && (i <= j + 1 ||
isPal[i - 1][j + 1])) {
isPal[i][j] = true;
min = Math.min(min, j == 0 ? 0 : 1 + cut[j - 1]);
}
}
cut[i] = min;
}
return cut[str.length() - 1];
}

/**
* Given a string s, partition s such that every substring of the
partition is a palindrome.
* https://leetcode.com/problems/palindrome-partitioning/
*/
public List<List<String>> partition(String s) {
Map<Integer, List<List<String>>> dp = new HashMap<>();
List<List<String>> result = partitionUtil(s, dp, 0);
List<List<String>> r = new ArrayList<>();
for (List<String> l : result) {
r.add(l);
}
return r;
}

private List<List<String>> partitionUtil(String s, Map<Integer,


List<List<String>>> dp, int start) {
if (start == s.length()) {
List<String> r = new ArrayList<>();
return Collections.singletonList(r);
}

if (dp.containsKey(start)) {
return dp.get(start);
}

List<List<String>> words = new ArrayList<>();


for (int i = start; i < s.length(); i++) {
if (!isPalindrome(s, start, i) ) {
continue;
}
String newWord = s.substring(start, i + 1);
List<List<String>> result = partitionUtil(s, dp, i + 1);
for (List l : result) {
List<String> l1 = new ArrayList<>();
l1.add(newWord);
l1.addAll(l);
words.add(l1);
}
}
dp.put(start, words);
return words;
}

private boolean isPalindrome(String str, int r, int t) {


while(r < t) {
if (str.charAt(r) != str.charAt(t)) {
return false;
}
r++;
t--;
}
return true;
}
}

package com.interview.dynamic;

/**
* Paint House 2
* https://leetcode.com/problems/paint-house-ii/
*/
public class PaintHouse {
public int minCost(int[][] costs) {
if (costs.length == 0 || costs[0].length == 0) {
return 0;
}
int[][] dp = new int[costs.length][costs[0].length];
for (int i = 0; i < costs[0].length; i++) {
dp[0][i] = costs[0][i];
}

for (int i = 1; i < costs.length; i++) {


Pair p = findMinSecondMin(dp[i - 1]);
for (int j = 0; j < costs[0].length; j++) {
dp[i][j] = costs[i][j];
if (j == p.minIndex) {
dp[i][j] += dp[i-1][p.secondMinIndex];
} else {
dp[i][j] += dp[i-1][p.minIndex];
}
}
}
int min = Integer.MAX_VALUE;
for (int i = 0; i < dp[0].length; i++) {
min = Math.min(min, dp[dp.length - 1][i]);
}
return min;
}

class Pair {
int minIndex;
int secondMinIndex;
}

private Pair findMinSecondMin(int[] input) {


int minIndex;
int secondMinIndex;
if (input[0] < input[1]) {
minIndex = 0;
secondMinIndex = 1;
} else {
minIndex = 1;
secondMinIndex = 0;
}
for (int i = 2; i < input.length; i++) {
if (input[i] < input[minIndex]) {
secondMinIndex = minIndex;
minIndex = i;
} else if (input[i] < input[secondMinIndex]) {
secondMinIndex = i;
}
}
Pair p = new Pair();
p.minIndex = minIndex;
p.secondMinIndex = secondMinIndex;
return p;
}

public static void main(String args[]) {


PaintHouse ph = new PaintHouse();
int[][] input = {{1, 2, 1}, {1, 4, 5}, {2, 6, 1}, {3, 3, 2}};
System.out.println(ph.minCost(input));
}
}

package com.interview.dynamic;

/**
* http://www.geeksforgeeks.org/dynamic-programming-set-24-optimal-
binary-search-tree/
*/
public class OptimalTreeSearch {

public int minCostRec(int input[],int freq[]){

return minCostRec(input,freq,0,input.length-1,1);
}

private int minCostRec(int input[],int freq[],int low,int high,int


level){
if(low > high){
return 0;
}

int min = Integer.MAX_VALUE;


for(int i=low; i <= high; i++){
int val = minCostRec(input,freq,low,i-1,level+1) +
minCostRec(input,freq,i+1,high,level+1)
+ level*freq[i];
if(val < min){
min = val;
}
}
return min;
}

public int minCost(int input[], int freq[]){


int T[][] = new int[input.length][input.length];

for(int i=0; i < T.length; i++){


T[i][i] = freq[i];
}

for(int l = 2; l <= input.length; l++){


for(int i=0; i <= input.length-l; i++){
int j = i + l -1;
T[i][j] = Integer.MAX_VALUE;
int sum = getSum(freq, i, j);

for(int k=i; k <= j; k++){


int val = sum + (k-1 < i ? 0 : T[i][k-1]) +
(k+1 > j ? 0 : T[k+1][j]) ;
if(val < T[i][j]){
T[i][j] = val;
}
}
}
}
return T[0][input.length-1];
}

private int getSum(int freq[], int i, int j){


int sum = 0;
for(int x = i; x <= j; x++){
sum += freq[x];
}
return sum;
}

public static void main(String args[]){


int input[] = {10,12,20,35,46};
int freq[] = {34,8,50,21,16};
OptimalTreeSearch ots = new OptimalTreeSearch();
System.out.println(ots.minCost(input, freq));
System.out.println(ots.minCostRec(input, freq));
}
}

package com.interview.dynamic;

/**
* Finding the number of ways a given score could be reached for a
game with 3 different ways of scoring (e.g. 3, 5 and 10 points).
*test case
*what happens if total can't be formed with given values
*what if numbers are 0 or negative
*/
public class NumberOfWaysToScorePoints {

//in this version to make 3 - 1,2 is same as 2,1.


//This is similar to coin changing problem
public int version1(int score[],int total){
int T[] = new int[total+1];
T[0] = 1;
for(int i=0; i < score.length; i++){
for(int j=1; j <= total; j++){
if(score[i] <= j){
T[j] += T[j-score[i]];
}
}
}
return T[total];
}

//in this version to make 3 - 1,2 and 2,1 are counted different.
//This is same as fibo series only that fibo series looks at last
2 numbers and here we look back k values
public int version2(int score[],int total){
int T[] = new int[total+1];
T[0] = 1;
for(int i=1; i <= total ; i++){
for(int j=0; j < score.length; j++){
if(score[j] <= i){
T[i] += T[i-score[j]];
}
}
}
return T[total];
}

public static void main(String args[]){


int score[] = {1,2,3};
NumberOfWaysToScorePoints now = new
NumberOfWaysToScorePoints();
System.out.println(now.version1(score, 4));
System.out.println(now.version2(score, 4));
}
}

package com.interview.dynamic;

/**
* http://www.geeksforgeeks.org/count-possible-paths-top-left-bottom-
right-nxm-matrix/
*/
public class NumberOfPathsInMxNMatrix {

public int countPathsRecursive(int n, int m){


if(n == 1 || m == 1){
return 1;
}
return countPathsRecursive(n-1, m) + countPathsRecursive(n, m-
1);
}

public int countPaths(int n,int m){


int T[][] = new int[n][m];
for(int i=0; i < n; i++){
T[i][0] = 1;
}

for(int i=0; i < m; i++){


T[0][i] = 1;
}
for(int i=1; i < n; i++){
for(int j=1; j < m; j++){
T[i][j] = T[i-1][j] + T[i][j-1];
}
}
return T[n-1][m-1];
}

public static void main(String args[]){


NumberOfPathsInMxNMatrix nop = new NumberOfPathsInMxNMatrix();
System.out.print(nop.countPathsRecursive(3,3));
}

package com.interview.dynamic;

/**
* http://www.glassdoor.com/Interview/N-pots-each-with-some-number-of-
gold-coins-are-arranged-in-a-line-You-are-playing-a-game-against-
another-player-You-tak-QTN_350584.htm
* @author tusroy
* @author Z. Berkay Celik
*/
public class NPotGold {

static class Pair{


int first, second;
int pick=0;
public String toString(){
return first + " " + second + " " + pick;
}
}
public Pair[][] findMoves(int pots[]){

Pair[][] moves = new Pair[pots.length][pots.length];

for(int i=0; i < moves.length; i++){


for(int j=0; j < moves[i].length; j++){
moves[i][j] = new Pair();
}
}

for(int i=0; i < pots.length; i++){


moves[i][i].first = pots[i];
//to track the sequence of moves
moves[i][i].pick = i;
}

for(int l = 2; l <= pots.length; l++){


for(int i=0; i <= pots.length - l; i++){
int j = i + l -1;
if(pots[i] + moves[i+1][j].second > moves[i][j-
1].second + pots[j]){
moves[i][j].first = pots[i] +
moves[i+1][j].second;
moves[i][j].second = moves[i+1][j].first;
moves[i][j].pick = i;
}else{
moves[i][j].first = pots[j] + moves[i][j-
1].second;
moves[i][j].second = moves[i][j-1].first;
moves[i][j].pick =j;
}
}
}

return moves;
}
//prints the sequence of values and indexes
public void printSequence(int pots[], Pair moves[][]){
int i = 0;
int j = pots.length - 1;
int step;
for (int k = 0; k < pots.length; k++) {
step = moves[i][j].pick;
//this is the value of pick and its index
System.out.print("value: " + pots[step] + " " + "index: "
+ step + " ");
if (step <= i) {
i = i + 1;
} else {
j = j - 1;
}
}
}
public static void main(String args[]){
NPotGold npg = new NPotGold();
int pots[] = {3,1,5,6,2,9,3};
Pair[][] moves = npg.findMoves(pots);
for(int i=0; i < moves.length; i++){
for(int j=0; j < moves[i].length; j++){
System.out.print(moves[i][j] + " ");
}
System.out.print("\n");
}
System.out.println("The moves by first player and second
player:");
npg.printSequence(pots, moves);
}
}

package com.interview.dynamic;

import java.util.Arrays;

/**
* Date 06/12/2014
* @author tusroy
*
* Given an array of non negative integers where each element
represents the max
* number of steps that can be made forward from that element. Write a
function to
* return the minimum number of jumps to reach the end of the array
from first element
*
* Solution
* Have 2 for loop. j trails i. If arr[j] + j >= i then you calculate
new jump
* and result.
*
* Space complexity O(n) to maintain result and min jumps
* Time complexity O(n^2)
*
* Reference
* http://www.geeksforgeeks.org/minimum-number-of-jumps-to-reach-end-
of-a-given-array/
*/
public class MinJumpToReachEnd {
public int minJump(int arr[],int result[]){

int []jump = new int[arr.length];


jump[0] = 0;
for(int i=1; i < arr.length ; i++){
jump[i] = Integer.MAX_VALUE-1;
}

for(int i=1; i < arr.length; i++){


for(int j=0; j < i; j++){
if(arr[j] + j >= i){
if(jump[i] > jump[j] + 1){
result[i] = j;
jump[i] = jump[j] + 1;
}
}
}
}

return jump[jump.length-1];
}

/**
* https://leetcode.com/problems/jump-game-ii/
*/
public int jump(int[] nums) {
if (nums.length == 1) {
return 0;
}
int count = 0;
int i = 0;
while (i + nums[i] < nums.length - 1) {
int maxVal = 0;
int maxValIndex = 0;
for (int j = 1; j <= nums[i]; j++) {
if (nums[j + i] + j > maxVal) {
maxVal = nums[j + i] + j;
maxValIndex = i + j;
}
}
i = maxValIndex;
count++;
}
return count + 1;
}

public static void main(String args[]){


MinJumpToReachEnd mj = new MinJumpToReachEnd();
int arr[] = {1,3,5,3,2,2,6,1,6,8,9};
int r[] = new int[arr.length];
int result = mj.minJump(arr,r);
System.out.println(result);
int i = arr.length-1;
Arrays.toString(r);
int arr1[] = {2,3,1,1,4};
System.out.print(mj.jump(arr));
}
}

package com.interview.dynamic;

import java.util.List;

/**
* Given a triangle, find the minimum path sum from top to bottom.
Each step you may move to adjacent numbers on
* the row below.
* https://leetcode.com/problems/triangle/
*/
public class MinimumTriangleSum {
public int minimumTotal(List<List<Integer>> triangle) {
int n = triangle.size();
int[] dp = new int[n];

for (int i = 0; i < triangle.get(n - 1).size(); i++) {


dp[i] = triangle.get(n - 1).get(i);
}

for (int i = triangle.size() - 2; i >= 0; i--) {


for (int j = 0; j < triangle.get(i).size(); j++) {
dp[j] = triangle.get(i).get(j) + Math.min(dp[j], dp[j
+ 1]);
}
}
return dp[0];
}
}

package com.interview.dynamic;

import java.util.*;

/**
* Date 10/19/2016
* @author Tushar Roy
*
* Given a positive integer n, find the least number of perfect square
numbers (for example, 1, 4, 9, 16, ...) which sum to n.
* For example, given n = 12, return 3 because 12 = 4 + 4 + 4; given n
= 13, return 2 because 13 = 4 + 9.
*
* Solution 1 - Using DP similar to coin change problem with infinite
supply
* Solution 2 - Using a BFS. Put all perfect squares in queue. Then
considering each as a node try adding
* another perfect square and see if we can get n. Keep doing this in
BFS fashion till you hit the number.
*
* https://leetcode.com/problems/perfect-squares/
*/
public class MinimumNumberOfPerfectSquares {
public int numSquaresUsingDP(int n) {
int count = (int)Math.ceil(Math.sqrt(n));

int[] T = new int[n + 1];

T[0] = 0;

for (int i = 1; i < T.length; i++) {


T[i] = Integer.MAX_VALUE;
for (int j = 1; j <= count; j++) {
if (i < j*j) {
break;
}
T[i] = Math.min(T[i], T[i - j*j] + 1);
}
}
return T[n];
}

public int numSquaresUsingBFS(int n) {


List<Integer> perfectSquares = new ArrayList<>();
int i = 1;
Queue<Integer> queue = new LinkedList<>();
Set<Integer> visited = new HashSet<>();
while (true) {
int square = i * i;
if (square == n) {
return 1;
}
if (square > n) {
break;
}
perfectSquares.add(square);
queue.offer(square);
visited.add(square);
i++;
}
int distance = 1;
while (!queue.isEmpty()) {
int size = queue.size();
distance++;
for (int j = 0; j < size; j++) {
int node = queue.poll();
for (int square : perfectSquares) {
int sum = node + square;
if (sum == n) {
return distance;
} else if (!visited.contains(sum)) {
visited.add(sum);
queue.add(sum);
} else if (sum > n) {
break;
}
}
}
}
return distance;
}
}

package com.interview.dynamic;

/**
* http://www.geeksforgeeks.org/find-the-minimum-cost-to-reach-a-
destination-where-every-station-is-connected-in-one-direction/
*/
public class MinimumCostTrainTicket {

public int minCost(int ticket[][]){


assert ticket != null && ticket.length > 0 && ticket.length ==
ticket[0].length;
int T[] = new int[ticket.length];
int T1[] = new int[ticket.length];
T1[0] = -1;
for(int i=1; i < T.length; i++){
T[i] = ticket[0][i];
T1[i] = i-1;
}

for(int i=1; i < T.length; i++){


for(int j=i+1; j < T.length; j++){
if(T[j] > T[i] + ticket[i][j]){
T[j] = T[i] + ticket[i][j];
T1[j] = i;
}
}
}
//printing actual stations
int i = ticket.length-1;
while(i != -1){
System.out.print(i + " ");
i = T1[i];
}
System.out.println();
return T[ticket.length-1];
}

public static void main(String args[]){


int input[][] = {{0, 15, 80, 90},
{-1, 0, 40, 50},
{-1, -1, 0, 70},
{-1, -1, -1, 0}};
MinimumCostTrainTicket mctt = new MinimumCostTrainTicket();
System.out.println(mctt.minCost(input));
}
}

package com.interview.dynamic;

/**
* http://www.geeksforgeeks.org/dynamic-programming-set-6-min-cost-
path/
*/
public class MinCostPath {

public int minCost(int [][]cost,int m,int n){

int temp[][] = new int[m+1][n+1];


int sum = 0;
for(int i=0; i <= n; i++){
temp[0][i] = sum + cost[0][i];
sum = temp[0][i];
}
sum = 0;
for(int i=0; i <= m; i++){
temp[i][0] = sum + cost[i][0];
sum = temp[i][0];
}

for(int i=1; i <= m; i++){


for(int j=1; j <= n; j++){
temp[i][j] = cost[i][j] + min(temp[i-1][j-1], temp[i-
1][j],temp[i][j-1]);
}
}
return temp[m][n];
}

public int minCostRec(int cost[][], int m, int n){


return minCostRec(cost, m, n, 0 , 0);
}

public int minCostRec(int cost[][], int m, int n, int x, int y){


if(x > m || y > n){
return Integer.MAX_VALUE;
}
if(x == m && y == n){
return cost[m][n];
}

int t1 = minCostRec(cost, m , n, x+1, y);


int t2 = minCostRec(cost, m , n, x+1, y+1);
int t3 = minCostRec(cost, m , n, x, y+1);

return cost[x][y] + min(t1,t2,t3);


}

private int min(int a,int b, int c){


int l = Math.min(a, b);
return Math.min(l, c);
}

public static void main(String args[]){


MinCostPath mcp = new MinCostPath();
int cost[][] = {{1,2,3},{4,8,2},{1,5,3},{6,2,9}};
int result = mcp.minCost(cost, 3, 2);
int result1 = mcp.minCostRec(cost, 3, 2);
System.out.println(result);
System.out.println(result1);
}

package com.interview.dynamic;

/**
* Date 11/03/2016
* @author Tushar Roy
*
* Find maximum sum for non adjacent elements.
* Variation is finding maximum sum non adjacent elements assuming its
a circular array.
* So first element cannot be with last element.
*
* Time complexity O(n)
* Space complexity O(1)
*
* https://leetcode.com/problems/house-robber/
* https://leetcode.com/problems/house-robber-ii/
*/
public class MaxSumForNonAdjacentElements {

/**
* Fast DP solution.
*/
public int maxSum(int arr[]) {
int excl = 0;
int incl = arr[0];
for (int i = 1; i < arr.length; i++) {
int temp = incl;
incl = Math.max(excl + arr[i], incl);
excl = temp;
}
return incl;
}

/**
* Recursive slow solution.
*/
public int maxSum(int arr[], int index) {
if (index == 0) {
return arr[0];
} else if (index == 1) {
return Math.max(arr[0], arr[1]);
}
return Math.max(this.maxSum(arr, index - 2) + arr[index],
this.maxSum(arr, index - 1));
}

/**
* Find maximum sum from left to right ignoring first element.
* Find maximum sum from right to left ignoring last element.
* Maximum of two will be the answer. It gurantees that both first
and last element
* will be not selected together.
*/
public int maxSumCircularArray(int[] nums) {
if (nums.length == 0) {
return 0;
}
if (nums.length == 1) {
return nums[0];
}
int with = nums[1];
int without = 0;
for (int i = 2; i < nums.length; i++) {
int newWith = without + nums[i];
without = with;
with = Math.max(with, newWith);
}

int with1 = nums[nums.length - 2];


int without1 = 0;
for (int i = nums.length - 3; i >= 0; i--) {
int newWith1 = without1 + nums[i];
without1 = with1;
with1 = Math.max(with1, newWith1);
}
return Math.max(with, with1);
}

public static void main(String args[]) {


MaxSumForNonAdjacentElements msn = new
MaxSumForNonAdjacentElements();
int arr[] = { 2, 10, 13, 4, 2, 15, 10 };
System.out.println(msn.maxSum(arr));
System.out.println(msn.maxSum(arr, arr.length-1));

}
}

/**
* Problem Statement:
*
* Given an array of n positive integers. Write a program to find the
sum of maximum sum subsequence of the given array
* such that the integers in the subsequence are in increasing order.
*
*
* Video: https://youtu.be/99ssGWhLPUE
*
* Reference:
* http://www.geeksforgeeks.org/dynamic-programming-set-14-maximum-
sum-increasing-subsequence/
*/
public class MaximumSumSubsequence {

public int maxSum(int arr[]){


int T[] = new int[arr.length];

for (int i = 0; i < T.length; i++) {


T[i] = arr[i];
}

for(int i=1; i < T.length; i++){


for(int j = 0; j < i; j++){
if(arr[j] < arr[i]){
T[i] = Math.max(T[i], T[j] + arr[i]);
}
}
}

int max = T[0];


for (int i=1; i < T.length; i++){
if(T[i] > max){
max = T[i];
}
}
return max;
}

public static void main(String args[]){


MaximumSumSubsequence mss = new MaximumSumSubsequence();
int arr[] = {1, 101, 10, 2, 3, 100,4};
int r = mss.maxSum(arr);
System.out.print(r);
}
}

package com.interview.dynamic;

/**
* http://www.geeksforgeeks.org/maximum-size-sub-matrix-with-all-1s-
in-a-binary-matrix/
*/
public class MaximumSizeSubMatrix {

private int min(int a,int b, int c){


int l = Math.min(a, b);
return Math.min(l, c);
}

public int maxSize(int arr[][]){

int result[][] = new int[arr.length][arr[0].length];


int max = 0;
for(int i=0; i < arr.length; i++){
result[i][0] = arr[i][0];
if (result[i][0] == 1)
{
max = 1;
}
}
for(int i=0; i < arr[0].length; i++){
result[0][i] = arr[0][i];
if (result[0][i] == 1)
{
max = 1;
}

for(int i=1; i < arr.length; i++){


for(int j=1; j < arr[i].length; j++){
if(arr[i][j] == 0){
continue;
}
int t = min(result[i-1][j],result[i-1][j-
1],result[i][j-1]);
result[i][j] = t +1;
if(result[i][j] > max){
max = result[i][j];
}
}
}
return max;
}

public static void main(String args[]){

int arr[][] =
{{0,1,1,0,1},{1,1,1,0,0},{1,1,1,1,0},{1,1,1,0,1}};
MaximumSizeSubMatrix mssm = new MaximumSizeSubMatrix();
int result = mssm.maxSize(arr);
System.out.print(result);
}

package com.interview.dynamic;

import com.interview.stackqueue.MaximumHistogram;

/**
* Date 06/23/2014
* @author tusroy
*
* Video link - https://youtu.be/2xvJ41-hsoE
*
* Given a 2D matrix of 0s and 1s. Find largest rectangle of all 1s
* in this matrix.
*
* Maintain a temp array of same size as number of columns.
* Copy first row to this temp array and find largest rectangular area
* for histogram. Then keep adding elements of next row to this temp
* array if they are not zero. If they are zero then put zero there.
* Every time calculate max area in histogram.
*
* Time complexity - O(rows*cols)
* Space complexity - O(cols) - if number of cols is way higher than
rows
* then do this process for rows and not columns.
*
* References:
* http://www.careercup.com/question?id=6299074475065344
*/
public class MaximumRectangularSubmatrixOf1s {

public int maximum(int input[][]){


int temp[] = new int[input[0].length];
MaximumHistogram mh = new MaximumHistogram();
int maxArea = 0;
int area = 0;
for(int i=0; i < input.length; i++){
for(int j=0; j < temp.length; j++){
if(input[i][j] == 0){
temp[j] = 0;
}else{
temp[j] += input[i][j];
}
}
area = mh.maxHistogram(temp);
if(area > maxArea){
maxArea = area;
}
}
return maxArea;
}

public static void main(String args[]){


int input[][] = {{1,1,1,0},
{1,1,1,1},
{0,1,1,0},
{0,1,1,1},
{1,0,0,1},
{1,1,1,1}};
MaximumRectangularSubmatrixOf1s mrs = new
MaximumRectangularSubmatrixOf1s();
int maxRectangle = mrs.maximum(input);
//System.out.println("Max rectangle is of size " +
maxRectangle);
assert maxRectangle == 8;
}
}

package com.interview.dynamic;

/**
* http://www.geeksforgeeks.org/dynamic-programming-set-36-cut-a-rope-
to-maximize-product/
*/
public class MaximumProductCutting {

public int maxProduct(int num){


int T[] = new int[num+1];
T[0] = 1;
for(int i=1; i <= num; i++){
T[i] = i;
}
for(int i=2; i <= num; i++){
for(int j=1; j <= i; j++){
T[i] = Math.max(T[i],T[j]*T[i-j]);
}
}
return T[num];
}

public static void main(String args[]){


MaximumProductCutting mpc = new MaximumProductCutting();
System.out.println(mpc.maxProduct(13));
}
}

package com.interview.dynamic;

import java.util.Arrays;

/**
* http://www.geeksforgeeks.org/dynamic-programming-set-20-maximum-
length-chain-of-pairs/
*/
public class MaximumLengthChainPair {

static class Pair implements Comparable<Pair>{


public Pair(int a,int b){
this.a = a;
this.b = b;
}
int a;
int b;
@Override
public int compareTo(Pair o) {
if(this.a <= o.a){
return -1;
}else{
return 1;
}
}
}

public int maxLength(Pair[] arr){


Arrays.sort(arr);

int T[] = new int[arr.length+1];


for(int i=0; i < T.length; i++){
T[i] = 1;
}
for(int i=2; i < T.length; i++){
for(int j=1; j < i; j++){
if(arr[j-1].b < arr[i-1].a){
T[i] = Math.max(T[j] + 1, T[i]);
}
}
}

int max =0 ;
for(int i=1; i <T.length; i++){
if(max < T[i]){
max = T[i];
}
}
return max;
}

public static void main(String args[]){


Pair p = new Pair(5,7);
Pair p1 = new Pair(2,3);
Pair p2 = new Pair(2,6);
Pair p3 = new Pair(9,11);
Pair p4 = new Pair(8,10);
Pair p5 = new Pair(11,14);

Pair[] arr = {p,p1,p2,p3,p4,p5};


MaximumLengthChainPair mlcp = new MaximumLengthChainPair();
int r = mlcp.maxLength(arr);
System.out.print(r);
}
}

You might also like