From 8856d98cf1bce574dae94309456568df78b89bcf Mon Sep 17 00:00:00 2001 From: Sourav Kumar Bhunia Date: Tue, 3 Oct 2023 21:14:32 +0530 Subject: [PATCH] Added Dynamic Programming Hacktoberfest --- .../DP/Cutting_rod.cpp | 96 +++++++++++++++++++ .../DP/DP_on_tree/Diameter_of_tree.cpp | 36 +++++++ .../02 Knapsack Memoization(DP).cpp | 46 +++++++++ .../DP/Knapsack0_1/03 Knapsack Bottom up.cpp | 44 +++++++++ .../04 Subset sum(Knapsack variation).cpp | 48 ++++++++++ .../DP/Knapsack0_1/05 Equal sum partition.cpp | 57 +++++++++++ .../06 Count of Subsets with given Sum.cpp | 47 +++++++++ .../07 Minimum subset sum difference.cpp | 54 +++++++++++ ...number of subset with given difference.cpp | 51 ++++++++++ .../DP/Knapsack0_1/09 Target sum.cpp | 49 ++++++++++ .../DP/Knapsack0_1/10 Unbounded Knapsack.cpp | 35 +++++++ .../DP/Knapsack0_1/11 Rod cutting problem.cpp | 37 +++++++ ...in change problem _ maximum no of ways.cpp | 35 +++++++ ...change problem_ Minimum number of coin.cpp | 44 +++++++++ .../DP/Knapsack0_1/knapsack_recursive.cpp | 36 +++++++ ...mmon Subsequence Top down(Memoization).cpp | 34 +++++++ ...ngest Common Subsequence Bottom Up(DP).cpp | 32 +++++++ .../DP/LCS/17 LCS Substring.cpp | 37 +++++++ .../DP/LCS/18 Print LCS.cpp | 46 +++++++++ .../LCS/19 Shortest Common Supersequence.cpp | 34 +++++++ ...m insertion deletion to convert a to b.cpp | 35 +++++++ .../21 Longest Palindromic Subsequence.cpp | 35 +++++++ ... deletions to make a string palindrome.cpp | 40 ++++++++ ...23 Print Shortest Common Supersequence.cpp | 58 +++++++++++ .../LCS/24 Longest repeating subsequence.cpp | 29 ++++++ .../DP/LCS/25 Sequence pattern matching.cpp | 33 +++++++ ... insertion to make a string palindrome.cpp | 39 ++++++++ .../DP/LCS/longest_common_subsequence.cpp | 24 +++++ .../37 Egg dropping problem recursive.cpp | 25 +++++ .../38 Egg dropping problem top down.cpp | 33 +++++++ ...pping problem memoization optimization.cpp | 47 +++++++++ .../Evaluate Expression to true Recursive.cpp | 69 +++++++++++++ ...ate Expression to true using 3D matrix.cpp | 79 +++++++++++++++ .../Evaluate Expression to true using map.cpp | 80 ++++++++++++++++ .../egg_dropping_recursive.cpp | 32 +++++++ .../DP/Matrix_Chain_Multiplication/mcm.cpp | 40 ++++++++ .../mcm_using_memo.cpp | 48 ++++++++++ .../palindrome_partitioning.cpp | 50 ++++++++++ .../palindrome_partitioning_using_memo.cpp | 81 ++++++++++++++++ .../scrambled_string_memoized.cpp | 51 ++++++++++ .../scrambled_string_recursive.cpp | 44 +++++++++ .../DP/Travelling_salesman.cpp | 66 +++++++++++++ 42 files changed, 1936 insertions(+) create mode 100644 Data Structures and Algorithm/DP/Cutting_rod.cpp create mode 100644 Data Structures and Algorithm/DP/DP_on_tree/Diameter_of_tree.cpp create mode 100644 Data Structures and Algorithm/DP/Knapsack0_1/02 Knapsack Memoization(DP).cpp create mode 100644 Data Structures and Algorithm/DP/Knapsack0_1/03 Knapsack Bottom up.cpp create mode 100644 Data Structures and Algorithm/DP/Knapsack0_1/04 Subset sum(Knapsack variation).cpp create mode 100644 Data Structures and Algorithm/DP/Knapsack0_1/05 Equal sum partition.cpp create mode 100644 Data Structures and Algorithm/DP/Knapsack0_1/06 Count of Subsets with given Sum.cpp create mode 100644 Data Structures and Algorithm/DP/Knapsack0_1/07 Minimum subset sum difference.cpp create mode 100644 Data Structures and Algorithm/DP/Knapsack0_1/08 Count the number of subset with given difference.cpp create mode 100644 Data Structures and Algorithm/DP/Knapsack0_1/09 Target sum.cpp create mode 100644 Data Structures and Algorithm/DP/Knapsack0_1/10 Unbounded Knapsack.cpp create mode 100644 Data Structures and Algorithm/DP/Knapsack0_1/11 Rod cutting problem.cpp create mode 100644 Data Structures and Algorithm/DP/Knapsack0_1/12 Coin change problem _ maximum no of ways.cpp create mode 100644 Data Structures and Algorithm/DP/Knapsack0_1/13 Coin change problem_ Minimum number of coin.cpp create mode 100644 Data Structures and Algorithm/DP/Knapsack0_1/knapsack_recursive.cpp create mode 100644 Data Structures and Algorithm/DP/LCS/15 Longest Common Subsequence Top down(Memoization).cpp create mode 100644 Data Structures and Algorithm/DP/LCS/16 Longest Common Subsequence Bottom Up(DP).cpp create mode 100644 Data Structures and Algorithm/DP/LCS/17 LCS Substring.cpp create mode 100644 Data Structures and Algorithm/DP/LCS/18 Print LCS.cpp create mode 100644 Data Structures and Algorithm/DP/LCS/19 Shortest Common Supersequence.cpp create mode 100644 Data Structures and Algorithm/DP/LCS/20 Minimum insertion deletion to convert a to b.cpp create mode 100644 Data Structures and Algorithm/DP/LCS/21 Longest Palindromic Subsequence.cpp create mode 100644 Data Structures and Algorithm/DP/LCS/22 Minimum number of deletions to make a string palindrome.cpp create mode 100644 Data Structures and Algorithm/DP/LCS/23 Print Shortest Common Supersequence.cpp create mode 100644 Data Structures and Algorithm/DP/LCS/24 Longest repeating subsequence.cpp create mode 100644 Data Structures and Algorithm/DP/LCS/25 Sequence pattern matching.cpp create mode 100644 Data Structures and Algorithm/DP/LCS/26 Minimum Number of insertion to make a string palindrome.cpp create mode 100644 Data Structures and Algorithm/DP/LCS/longest_common_subsequence.cpp create mode 100644 Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/37 Egg dropping problem recursive.cpp create mode 100644 Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/38 Egg dropping problem top down.cpp create mode 100644 Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/39 Egg dropping problem memoization optimization.cpp create mode 100644 Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/Evaluate Expression to true Recursive.cpp create mode 100644 Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/Evaluate Expression to true using 3D matrix.cpp create mode 100644 Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/Evaluate Expression to true using map.cpp create mode 100644 Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/egg_dropping_recursive.cpp create mode 100644 Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/mcm.cpp create mode 100644 Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/mcm_using_memo.cpp create mode 100644 Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/palindrome_partitioning.cpp create mode 100644 Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/palindrome_partitioning_using_memo.cpp create mode 100644 Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/scrambled_string_memoized.cpp create mode 100644 Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/scrambled_string_recursive.cpp create mode 100644 Data Structures and Algorithm/DP/Travelling_salesman.cpp diff --git a/Data Structures and Algorithm/DP/Cutting_rod.cpp b/Data Structures and Algorithm/DP/Cutting_rod.cpp new file mode 100644 index 0000000..8126dd9 --- /dev/null +++ b/Data Structures and Algorithm/DP/Cutting_rod.cpp @@ -0,0 +1,96 @@ +#include +using namespace std; + +// Top up method:- O(n ^ 2) + +int memoTopUpCutRod(vector p, int n, vector r) +{ + int q; + if(r[n] >= 0) + { + return r[n]; + } + if(n == 0) + { + q = 0; + } + else + { + q = INT_MIN; + } + for (int i = 1; i <= n; ++i) + { + q = max(q, p[i - 1] + memoTopUpCutRod(p, n - i, r)); + } + r[n] = q; + return q; +} + +int topUpCutRod(vector p, int n) +{ + vector r(n + 1, INT_MIN); + return memoTopUpCutRod(p, n, r); +} + +// Bottom up method:- O(n ^ 2) + +int bottomUpCutRod(vector p, int n) +{ + vector r(n + 1, INT_MIN); + r[0] = 0; + for (int i = 1; i <= n; ++i) + { + int q = -1; + for (int j = 1; j <= i; ++j) + { + q = max(q, p[j - 1] + r[i - j]); + } + r[i] = q; + } + return r[n]; +} + +// Optimal Bottom up solution:- + +// int printOptimalSol(vector p, int n) +// { +// auto [r, s] = OptimalBottomUp(p, n); +// while(n > 0) +// { +// cout << s[n] << " "; +// n -= s[n]; +// } +// } + +// OptimalBottomUp(vector p, int n) +// { +// vector r(n + 1); +// vector s(n); +// r[0] = 0; +// for (int j = 1; j <= n; ++j) +// { +// int q = INT_MIN; +// for (int i = 1; i <= j; ++i) +// { +// if(q < p[i - 1] + r[j - i]) +// { +// q = p[i - 1] + r[j - i]; +// s[j - 1] = i; +// } +// } +// r[j] = q; +// } +// return {move(r), move(s)}; +// } + +int main() +{ + vector p{1, 5, 8, 9, 10, 17, 17, 20, 24, 30}; + // vector p{1,3,4,5}; + int n = 4; + // int n = p.size(); + cout << bottomUpCutRod(p, n) << endl; + cout << topUpCutRod(p, n) << endl; + // cout << printOptimalSol(p, n) << endl; + return 0; +} diff --git a/Data Structures and Algorithm/DP/DP_on_tree/Diameter_of_tree.cpp b/Data Structures and Algorithm/DP/DP_on_tree/Diameter_of_tree.cpp new file mode 100644 index 0000000..c84cef4 --- /dev/null +++ b/Data Structures and Algorithm/DP/DP_on_tree/Diameter_of_tree.cpp @@ -0,0 +1,36 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +private: + int res; +public: + int Solve(TreeNode* root) { + if (root == NULL) + return 0; + + int l = Solve(root->left); + int r = Solve(root->right); + + int temp = 1 + max(l, r); + int ans = max(temp, l + r + 1); + res = max(res, ans); + return temp; + } + int diameterOfBinaryTree(TreeNode* root) { + if (root == NULL) + return 0; + + res = INT_MIN + 1; + Solve(root); + return res - 1; + } +}; diff --git a/Data Structures and Algorithm/DP/Knapsack0_1/02 Knapsack Memoization(DP).cpp b/Data Structures and Algorithm/DP/Knapsack0_1/02 Knapsack Memoization(DP).cpp new file mode 100644 index 0000000..ef2eac2 --- /dev/null +++ b/Data Structures and Algorithm/DP/Knapsack0_1/02 Knapsack Memoization(DP).cpp @@ -0,0 +1,46 @@ +#include +using namespace std; + +const int D = 1000; // DP - matrix dimension + +int t[D][D]; // DP matrix + +int Knapsack(int wt[], int val[], int W, int n) { + // base case + if (n == 0 || W == 0) + return 0; + + // if already calculated + + + if (t[n][W] != -1) + return t[n][W]; + + // else calculate + else { + if (wt[n - 1] <= W) + t[n][W] = max(val[n - 1] + Knapsack(wt, val, W - wt[n - 1], n - 1),Knapsack(wt, val, W, n - 1)); + else if (wt[n - 1] > W) + t[n][W] = Knapsack(wt, val, W, n - 1); + + return t[n][W]; + } +} + +signed main() { + int n; cin >> n; // number of items + int val[n], wt[n]; // values and wts array + for (int i = 0; i < n; i++) + cin >> wt[i]; + for (int i = 0; i < n; i++) + cin >> val[i]; + int W; cin >> W; // capacity + + // matrix initialization + for (int i = 0; i <= n; i++) + for (int j = 0; j <= W; j++) + t[i][j] = -1; // initialize matrix with -1 + + cout << Knapsack(wt, val, W, n) << endl; + return 0; +} diff --git a/Data Structures and Algorithm/DP/Knapsack0_1/03 Knapsack Bottom up.cpp b/Data Structures and Algorithm/DP/Knapsack0_1/03 Knapsack Bottom up.cpp new file mode 100644 index 0000000..5195573 --- /dev/null +++ b/Data Structures and Algorithm/DP/Knapsack0_1/03 Knapsack Bottom up.cpp @@ -0,0 +1,44 @@ +#include +using namespace std; + +int Knapsack(int wt[], int val[], int W, int n) { + int t[n + 1][W + 1]; // DP matrix + + for (int i = 0; i <= n; i++) { + for (int j = 0; j <= W; j++) { + if (i == 0 || j == 0) // base case // filling 1st row and 1st column of the matrix with zero as per the base condition of the recursive solution + t[i][j] = 0; + else if (wt[i - 1] <= j) { // current wt can fit in bag // this is for the choice diagram of the recursive solution + int val1 = val[i - 1] + t[i - 1][j - wt[i - 1]]; // take current wt // and after taking weight substract the inserted weight from the final weight + int val2 = t[i - 1][j]; // skip current wt + t[i][j] = max(val1, val2); + } + else if (wt[i - 1] > j) // current wt doesn't fit in bag + t[i][j] = t[i - 1][j]; // move to next + } + } + + return t[n][W]; +} + +int main() { + int n; cin >> n; // number of items + int val[n], wt[n]; // values and wts array + for (int i = 0; i < n; i++) + cin >> wt[i]; + for (int i = 0; i < n; i++) + cin >> val[i]; + int W; cin >> W; // capacity + + cout << Knapsack(wt, val, W, n) << endl; + return 0; +} + +/* Complexity Analysis: + +Time Complexity: O(N*W). +where ‘N’ is the number of weight element and ‘W’ is capacity. As for every weight element we traverse through all weight capacities 1<=w<=W. +Auxiliary Space: O(N*W). +The use of 2-D array of size ‘N*W’. +*/ +// https://www.geeksforgeeks.org/0-1-knapsack-problem-dp-10/ diff --git a/Data Structures and Algorithm/DP/Knapsack0_1/04 Subset sum(Knapsack variation).cpp b/Data Structures and Algorithm/DP/Knapsack0_1/04 Subset sum(Knapsack variation).cpp new file mode 100644 index 0000000..009b6e0 --- /dev/null +++ b/Data Structures and Algorithm/DP/Knapsack0_1/04 Subset sum(Knapsack variation).cpp @@ -0,0 +1,48 @@ +// https://www.geeksforgeeks.org/subset-sum-problem-dp-25/ +#include +using namespace std; + +bool isSubsetPossible(int arr[], int n, int sum) { + bool t[n + 1][sum + 1]; // DP - matrix + // initialization + // here we are setting 1st row and 1st column + // i denotes the size of the array + // j denotes the target sum (subset sum) + for (int i = 0; i <= n; i++) { // itereate as long it is less then length of the array + for (int j = 0; j <= sum; j++) { + if (i == 0)// when array(i) is empty than there is no meaning of sum of elements so return false + t[i][j] = false; + if (j == 0) // when sum(j) is zero and there is always a chance of empty subset so return it as true; + t[i][j] = true; + } + } +// start from 1 since 1st row and column is already considerd + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= sum; j++) { + if (arr[i - 1] <= j) + // after taking and element substract from the (sum) i.e -> in {3,8} 3 is taken then we want 11-3=8in the array + t[i][j] = t[i - 1][j - arr[i - 1]] || t[i - 1][j]; // either take or(||) do not take + else // if sum is less than array size just leave and increment + t[i][j] = t[i - 1][j]; + } + } + + return t[n][sum]; // at last return T/F +} + +int main() { + int n; cin >> n; + int arr[n]; + for (int i = 0; i < n; i++) + cin >> arr[i]; + int sum; cin >> sum; + + isSubsetPossible(arr, n, sum) ? cout << "Yes\n" : cout << "No\n"; + return 0; +} +/* +Complexity Analysis: + +Time Complexity: O(sum*n), where sum is the ‘target sum’ and ‘n’ is the size of array. +Auxiliary Space: O(sum*n), as the size of 2-D array is sum*n. +*/ diff --git a/Data Structures and Algorithm/DP/Knapsack0_1/05 Equal sum partition.cpp b/Data Structures and Algorithm/DP/Knapsack0_1/05 Equal sum partition.cpp new file mode 100644 index 0000000..77ed5ea --- /dev/null +++ b/Data Structures and Algorithm/DP/Knapsack0_1/05 Equal sum partition.cpp @@ -0,0 +1,57 @@ +// https://www.geeksforgeeks.org/partition-problem-dp-18/ +#include +using namespace std; + +bool isSubsetPossible(int arr[], int n, int sum) { + bool t[n + 1][sum + 1]; // DP - matrix + // initialization + // here we are setting 1st row and 1st column + // i denotes the size of the array + // j denotes the target sum (subset sum) + for (int i = 0; i <= n; i++) { // itereate as long it is less then length of the array + for (int j = 0; j <= sum; j++) { + if (i == 0)// when array(i) is empty than there is no meaning of sum of elements so return false + t[i][j] = false; + if (j == 0) // when sum(j) is zero and there is always a chance of empty subset so return it as true; + t[i][j] = true; + } + } +// start from 1 since 1st row and column is already considerd + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= sum; j++) { + if (arr[i - 1] <= j) + // after taking and element substract from the (sum) i.e -> in {3,8} 3 is taken then we want 11-3=8in the array + t[i][j] = t[i - 1][j - arr[i - 1]] || t[i - 1][j]; // either take or(||) do not take + else // if sum is less than array size just leave and increment + t[i][j] = t[i - 1][j]; + } + } + + return t[n][sum]; // at last return T/F +} + +bool EqualSumPartitionPossible(int arr[], int n) { + int sum = 0; // sum of all elements of arr + for (int i = 0; i < n; i++) // take the sum of array + sum += arr[i]; + + if (sum % 2 != 0) // if sum is odd --> not possible to make equal partitions + return false; + + return isSubsetPossible(arr, n, sum / 2); // when even divide sum of array into two part and apply subset sum +} + +int main() { + int n; cin >> n; + int arr[n]; + for (int i = 0; i < n; i++) + cin >> arr[i]; + + EqualSumPartitionPossible(arr, n) ? cout << "YES\n" : cout << "NO\n"; + return 0; +} + +/* +Time Complexity: O(sum * n) +Auxiliary Space: O(sum) +*/ diff --git a/Data Structures and Algorithm/DP/Knapsack0_1/06 Count of Subsets with given Sum.cpp b/Data Structures and Algorithm/DP/Knapsack0_1/06 Count of Subsets with given Sum.cpp new file mode 100644 index 0000000..9e60ba6 --- /dev/null +++ b/Data Structures and Algorithm/DP/Knapsack0_1/06 Count of Subsets with given Sum.cpp @@ -0,0 +1,47 @@ +// https://www.geeksforgeeks.org/count-of-subsets-with-sum-equal-to-x/ +#include +using namespace std; + +int CountSubsets(int arr[], int n, int sum) { + int t[n + 1][sum + 1]; // DP - matrix + // initialization + // here we are setting 1st row and 1st column + // i denotes the size of the array + // j denotes the target sum (subset sum) + for (int i = 0; i <= n; i++) { + for (int j = 0; j <= sum; j++) { + if (i == 0) // when array(i) is empty than there is no meaning of sum of elements so return count of subset as 0; + t[i][j] = 0; + if (j == 0) // when sum(j) is zero and there is always a chance of empty subset so return count as 1; + t[i][j] = 1; + } + } + + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= sum; j++) { + if (arr[i - 1] <= j) // when element in the list is less then target sum + t[i][j] = t[i - 1][j - arr[i - 1]] + t[i - 1][j]; // either exclude or inxlude and add both of them to get final count + else + t[i][j] = t[i - 1][j]; // exclude when element in the list is greater then the sum + } + } + + return t[n][sum]; // finally return the last row and last column element +} + +signed main() { + int n; cin >> n; + int arr[n]; + for (int i = 0; i < n; i++) + cin >> arr[i]; + int sum; cin >> sum; + + cout << CountSubsets(arr, n, sum) << endl; + return 0; +} + +/* +Time Complexity: O(sum*n), where the sum is the ‘target sum’ and ‘n’ is the size of the array. + +Auxiliary Space: O(sum*n), as the size of the 2-D array, is sum*n. +*/ diff --git a/Data Structures and Algorithm/DP/Knapsack0_1/07 Minimum subset sum difference.cpp b/Data Structures and Algorithm/DP/Knapsack0_1/07 Minimum subset sum difference.cpp new file mode 100644 index 0000000..4e18bda --- /dev/null +++ b/Data Structures and Algorithm/DP/Knapsack0_1/07 Minimum subset sum difference.cpp @@ -0,0 +1,54 @@ +#include +using namespace std; + +vector isSubsetPoss(int arr[], int n, int sum) { + bool t[n + 1][sum + 1]; // DP - matrix + // initialization + for (int i = 0; i <= n; i++) { + for (int j = 0; j <= sum; j++) { + if (i == 0) + t[i][j] = false; + if (j == 0) + t[i][j] = true; + } + } +// taking from the 2nd row and 2nd column + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= sum; j++) { + if (arr[i - 1] <= j) + t[i][j] = t[i - 1][j - arr[i - 1]] || t[i - 1][j]; // include or exclude + else + t[i][j] = t[i - 1][j]; // exclude + } + } + + vector v; // contains all subset sums possible with n elements // creating a vector varible to store all the element of the last row + for (int j = 0; j <= sum; j++) // from the range we need to exclude the element which is not there in the existing problem + if (t[n][j] == true) // keep true to only those place whose subset sum exist + v.push_back(j); // store in the vector + + return v; +} + +int MinSubsetSumDiff(int arr[], int n) { + int range = 0; + for (int i = 0; i < n; i++) + range += arr[i]; // taking sum of the array for range + + vector v = isSubsetPoss(arr, n, range); + int mn = INT_MAX; + for (int i = 0; i < v.size(); i++) // iterating through the last row of the matrix + mn = min(mn, abs(range - 2 * v[i])); // taking minimum from the last row + + return mn; +} + +signed main() { + int n; cin >> n; + int arr[n]; + for (int i = 0; i < n; i++) + cin >> arr[i]; + + cout << MinSubsetSumDiff(arr, n) << endl; + return 0; +} diff --git a/Data Structures and Algorithm/DP/Knapsack0_1/08 Count the number of subset with given difference.cpp b/Data Structures and Algorithm/DP/Knapsack0_1/08 Count the number of subset with given difference.cpp new file mode 100644 index 0000000..ba41ce5 --- /dev/null +++ b/Data Structures and Algorithm/DP/Knapsack0_1/08 Count the number of subset with given difference.cpp @@ -0,0 +1,51 @@ +#include +using namespace std; + +int CountSubsetsWithSum(int arr[], int n, int sum) { + int t[n + 1][sum + 1]; // DP - matrix + // initialization + // here we are setting 1st row and 1st column + // i denotes the size of the array + // j denotes the target sum (subset sum) + for (int i = 0; i <= n; i++) { + for (int j = 0; j <= sum; j++) { + if (i == 0) // when array(i) is empty than there is no meaning of sum of elements so return count of subset as 0; + t[i][j] = 0; + if (j == 0) // when sum(j) is zero and there is always a chance of empty subset so return count as 1; + t[i][j] = 1; + } + } + + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= sum; j++) { + if (arr[i - 1] <= j) // when element in the list is less then target sum + t[i][j] = t[i - 1][j - arr[i - 1]] + t[i - 1][j]; // either exclude or inxlude and add both of them to get final count + else + t[i][j] = t[i - 1][j]; // exclude when element in the list is greater then the sum + } + } + + return t[n][sum]; // finally return the last row and last column element +} + +int CountSubsetsWithDiff(int arr[], int n, int diff) { + int sumOfArray = 0; + for (int i = 0; i < n; i++) + sumOfArray += arr[i]; // taking sum of the array + + if ((sumOfArray + diff) % 2 != 0) + return 0; + else + return CountSubsetsWithSum(arr, n, (sumOfArray + diff) / 2);// we will get the number of array(subset) with particular sum +} + +signed main() { + int n; cin >> n; + int arr[n]; + for (int i = 0; i < n; i++) + cin >> arr[i]; + int diff; cin >> diff; + + cout << CountSubsetsWithDiff(arr, n, diff) << endl; + return 0; +} diff --git a/Data Structures and Algorithm/DP/Knapsack0_1/09 Target sum.cpp b/Data Structures and Algorithm/DP/Knapsack0_1/09 Target sum.cpp new file mode 100644 index 0000000..36879e1 --- /dev/null +++ b/Data Structures and Algorithm/DP/Knapsack0_1/09 Target sum.cpp @@ -0,0 +1,49 @@ + +class Solution { +public: + int CountSubsetsWithSum(vector& nums,int sum) { + int n= nums.size(); + int t[n + 1][sum + 1]; // DP - matrix + // initialization + t[0][0] = 1; + int k = 1; + for (int i = 0; i <= n; i++) { + for (int j = 0; j <= sum; j++) { + if (i == 0 && j > 0) + t[i][j] = 0; + if (j == 0 && i > 0) { + if (nums[i - 1] == 0) { + t[i][j] = pow(2, k); + k++; + } + else + t[i][j] = t[i - 1][j]; + } + } + } + + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= sum; j++) { + if (nums[i - 1] <= j) + t[i][j] = t[i - 1][j - nums[i - 1]] + t[i - 1][j]; + else + t[i][j] = t[i - 1][j]; + } + } + + return t[n][sum]; +} + int findTargetSumWays(vector& nums, int diff) { + int n= nums.size(); + int sumOfArray = 0; + for (int i = 0; i < n; i++) + sumOfArray += nums[i]; + + if ((sumOfArray + diff) % 2 != 0) + return 0; + else + return CountSubsetsWithSum(nums, (sumOfArray + diff) / 2); + + + } +}; diff --git a/Data Structures and Algorithm/DP/Knapsack0_1/10 Unbounded Knapsack.cpp b/Data Structures and Algorithm/DP/Knapsack0_1/10 Unbounded Knapsack.cpp new file mode 100644 index 0000000..c94ab4c --- /dev/null +++ b/Data Structures and Algorithm/DP/Knapsack0_1/10 Unbounded Knapsack.cpp @@ -0,0 +1,35 @@ +#include +using namespace std; + +int Un_knapsack(int wt[], int val[], int W, int n) { + int t[n + 1][W + 1]; // DP matrix + + for (int i = 0; i <= n; i++) { + for (int j = 0; j <= W; j++) { + if (i == 0 || j == 0) // base case + t[i][j] = 0; + else if (wt[i - 1] <= j) { // current wt can fit in bag + int val1 = val[i - 1] + t[i][j - wt[i - 1]]; // take current wt + int val2 = t[i - 1][j]; // skip current wt + t[i][j] = max(val1, val2); + } + else if (wt[i - 1] > j) // current wt doesn't fit in bag + t[i][j] = t[i - 1][j]; + } + } + + return t[n][W]; +} + +signed main() { + int n; cin >> n; // number of items + int val[n], wt[n]; // values and wts array + for (int i = 0; i < n; i++) + cin >> wt[i]; + for (int i = 0; i < n; i++) + cin >> val[i]; + int W; cin >> W; // capacity + + cout << Un_knapsack(wt, val, W, n) << endl; + return 0; +} diff --git a/Data Structures and Algorithm/DP/Knapsack0_1/11 Rod cutting problem.cpp b/Data Structures and Algorithm/DP/Knapsack0_1/11 Rod cutting problem.cpp new file mode 100644 index 0000000..46d8b4d --- /dev/null +++ b/Data Structures and Algorithm/DP/Knapsack0_1/11 Rod cutting problem.cpp @@ -0,0 +1,37 @@ +//https://www.geeksforgeeks.org/cutting-a-rod-dp-13/ +#include +using namespace std; + +int getMaxProfit(int length[], int price[], int n, int L) { + int dp[n + 1][L + 1]; + for (int i = 0; i <= n; i++) + for (int j = 0; j <= L; j++) + if (j == 0 || i == 0) + dp[i][j] = 0; + + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= L; j++) { + if (length[i - 1] <= j) { + dp[i][j] = max(dp[i - 1][j], + price[i - 1] + dp[i][j - length[i - 1]]); + } + else + dp[i][j] = dp[i - 1][j]; + } + } + + return dp[n][L]; +} + +signed main() { + int n; cin >> n; + int length[n], price[n]; + for (int i = 0; i < n; i++) + cin >> length[i]; + for (int i = 0; i < n; i++) + cin >> price[i]; + int L; cin >> L; + + cout << getMaxProfit(length, price, n, L) << endl; + return 0; +} diff --git a/Data Structures and Algorithm/DP/Knapsack0_1/12 Coin change problem _ maximum no of ways.cpp b/Data Structures and Algorithm/DP/Knapsack0_1/12 Coin change problem _ maximum no of ways.cpp new file mode 100644 index 0000000..99a9b21 --- /dev/null +++ b/Data Structures and Algorithm/DP/Knapsack0_1/12 Coin change problem _ maximum no of ways.cpp @@ -0,0 +1,35 @@ +#include +using namespace std; + +int getMaxNumberOfWays(int coins[], int n, int sum) { + int t[n + 1][sum + 1]; + // initialization + for (int i = 0; i <= n; i++) { + for (int j = 0; j <= sum; j++) { + if (i == 0) + t[i][j] = 0; + if (j == 0) + t[i][j] = 1; + } + } + + for (int i = 1; i <= n; i++) + for (int j = 1; j <= sum; j++) + if (coins[i - 1] <= j) + t[i][j] = t[i - 1][j] + t[i][j - coins[i - 1]]; + else + t[i][j] = t[i - 1][j]; + + return t[n][sum]; +} + +signed main() { + int n; cin >> n; + int coins[n]; + for (int i = 0; i < n; i++) + cin >> coins[i]; + int sum; cin >> sum; + + cout << getMaxNumberOfWays(coins, n, sum) << endl; + return 0; +} diff --git a/Data Structures and Algorithm/DP/Knapsack0_1/13 Coin change problem_ Minimum number of coin.cpp b/Data Structures and Algorithm/DP/Knapsack0_1/13 Coin change problem_ Minimum number of coin.cpp new file mode 100644 index 0000000..7d40090 --- /dev/null +++ b/Data Structures and Algorithm/DP/Knapsack0_1/13 Coin change problem_ Minimum number of coin.cpp @@ -0,0 +1,44 @@ +#include +using namespace std; +#define INF INT_MAX-1 + +int getMinNumberOfCoins(int coins[], int n, int sum) { + int t[n + 1][sum + 1]; + // initialization + for (int i = 0; i <= n; i++) { + for (int j = 0; j <= sum; j++) { + if (j == 0) + t[i][j] = 0; + if (i == 0) + t[i][j] = INF; + if (i == 1) { + if (j % coins[i - 1] == 0) + t[i][j] = j / coins[i - 1]; + else + t[i][j] = INF; + } + } + } + + t[0][0] = 0; + + for (int i = 1; i <= n; i++) + for (int j = 1; j <= sum; j++) + if (coins[i - 1] <= j) + t[i][j] = min(t[i - 1][j], 1 + t[i][j - coins[i - 1]]); + else + t[i][j] = t[i - 1][j]; + + return t[n][sum]; +} + +signed main() { + int n; cin >> n; + int coins[n]; + for (int i = 0; i < n; i++) + cin >> coins[i]; + int sum; cin >> sum; + + cout << getMinNumberOfCoins(coins, n, sum) << endl; + return 0; +} diff --git a/Data Structures and Algorithm/DP/Knapsack0_1/knapsack_recursive.cpp b/Data Structures and Algorithm/DP/Knapsack0_1/knapsack_recursive.cpp new file mode 100644 index 0000000..feac067 --- /dev/null +++ b/Data Structures and Algorithm/DP/Knapsack0_1/knapsack_recursive.cpp @@ -0,0 +1,36 @@ +#include +using namespace std; + +int Knapsack(int wt[], int val[], int W, int n) { + // every recursive solution will have a base condition + // for base condition we need to think of the smallest valid input that we can pass + // array size can be atleast 0 || min weight can be 0 but not negetive; + if (n == 0 || W == 0) + return 0; + + // these are the choices we are having + if (wt[n - 1] <= W) { + return max(val[n - 1] + Knapsack(wt, val, W - wt[n - 1], n - 1), + Knapsack(wt, val, W, n - 1)); + } + else if (wt[n - 1] > W) // if the weight is greater then the required weight there is no sence for taking that value. + return Knapsack(wt, val, W, n - 1); // return as it is by redusing the size of array + else + return -1; +} + +int main() { + int n,W; + cin >> n; // number of items + int val[n], wt[n]; // values and weights of array + for (int i = 0; i < n; i++) + cin >> wt[i]; + for (int i = 0; i < n; i++) + cin >> val[i]; + + cin >> W; // Knapsack capacity + + cout << Knapsack(wt, val, W, n) << endl; + return 0; +} +// T(N) = 2T(N-1) + O(1), which is simplified to O(2^N). diff --git a/Data Structures and Algorithm/DP/LCS/15 Longest Common Subsequence Top down(Memoization).cpp b/Data Structures and Algorithm/DP/LCS/15 Longest Common Subsequence Top down(Memoization).cpp new file mode 100644 index 0000000..43c6ec3 --- /dev/null +++ b/Data Structures and Algorithm/DP/LCS/15 Longest Common Subsequence Top down(Memoization).cpp @@ -0,0 +1,34 @@ +#include +using namespace std; + + +int dp[1001][1001]; + +int LCS(string X, string Y, int n, int m) { + // base case + if (n == 0 || m == 0) + dp[n][m] = 0; + + if (dp[n][m] != -1) // when table is not having -1 then return the value which is preseent in that block + return dp[n][m]; + + // choice diagram + // when last character is same + if (X[n - 1] == Y[m - 1]) + dp[n][m] = 1 + LCS(X, Y, n - 1, m - 1);// count the number and decreament the both's string length // store the value in particular block + // when last character is not same -> pick max + else + dp[n][m] = max(LCS(X, Y, n - 1, m), LCS(X, Y, n, m - 1)); // one take full and another by leaving last char and vice versa // store the value in particular block + + return dp[n][m]; +} + +int main() { + string X, Y; cin >> X >> Y; + int n = X.length(), m = Y.length(); + + memset(dp, -1, sizeof(dp)); // intialize the whole dp matrix with -1; // from memset we can initialise either -1 and zero; + + cout << LCS(X, Y, n, m) << endl; + return 0; +} diff --git a/Data Structures and Algorithm/DP/LCS/16 Longest Common Subsequence Bottom Up(DP).cpp b/Data Structures and Algorithm/DP/LCS/16 Longest Common Subsequence Bottom Up(DP).cpp new file mode 100644 index 0000000..5b888c3 --- /dev/null +++ b/Data Structures and Algorithm/DP/LCS/16 Longest Common Subsequence Bottom Up(DP).cpp @@ -0,0 +1,32 @@ + +#include +using namespace std; + +int LCS(string X, string Y, int n, int m) { + int dp[n + 1][m + 1]; // DP - matrix + + // initialize 1st row and of dp matrix with 0 according to the base condition of recursion // base case of recursion --> for initialization of dp - matrix + for (int i = 0; i <= n; i++) + for (int j = 0; j <= m; j++) + if (i == 0 || j == 0) + dp[i][j] = 0; +// choise diagram is used to fill rest of the matrix + for (int i = 1; i <= n; i++) + for (int j = 1; j <= m; j++) + if (X[i - 1] == Y[j - 1]) // when last character is same + dp[i][j] = 1 + dp[i - 1][j - 1]; + else // when last character is not same -> pick max + dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]); + + return dp[n][m]; // last row and last column element will give the length of the LCS; +} + +int main() { + string X, Y; cin >> X >> Y; + int n = X.length(), m = Y.length(); + + cout << LCS(X, Y, n, m) << endl; + return 0; +} + +// https://www.geeksforgeeks.org/longest-common-subsequence-dp-4/#:~:text=Time%20complexity%20of%20the%20above,length%20of%20LCS%20is%200.&text=In%20the%20above%20partial%20recursion,%E2%80%9D)%20is%20being%20solved%20twice. diff --git a/Data Structures and Algorithm/DP/LCS/17 LCS Substring.cpp b/Data Structures and Algorithm/DP/LCS/17 LCS Substring.cpp new file mode 100644 index 0000000..e1f87b6 --- /dev/null +++ b/Data Structures and Algorithm/DP/LCS/17 LCS Substring.cpp @@ -0,0 +1,37 @@ +#include +using namespace std; + +int LCSubstr(string X, string Y, int n, int m) { + int dp[n + 1][m + 1]; // DP - matrix + + // base condition + for (int i = 0; i <= n; i++) + for (int j = 0; j <= m; j++) + if (i == 0 || j == 0) + dp[i][j] = 0; // + + // choice diagram + for (int i = 1; i <= n; i++) + for (int j = 1; j <= m; j++) + if (X[i - 1] == Y[j - 1]) // when both string's last char is same + dp[i][j] = 1 + dp[i - 1][j - 1]; // count the number and decrement the table + else + dp[i][j] = 0; // variation from LCS(DP) + + int mx = INT_MIN; + for (int i = 0; i <= n; i++) + for (int j = 0; j <= m; j++) + mx = max(mx, dp[i][j]); + + return mx; +} + +int main() { + string X, Y; cin >> X >> Y; + int n = X.length(), m = Y.length(); + + cout << LCSubstr(X, Y, n, m) << endl; + return 0; +} + +// https://www.geeksforgeeks.org/longest-common-substring-dp-29/ diff --git a/Data Structures and Algorithm/DP/LCS/18 Print LCS.cpp b/Data Structures and Algorithm/DP/LCS/18 Print LCS.cpp new file mode 100644 index 0000000..67b9fb9 --- /dev/null +++ b/Data Structures and Algorithm/DP/LCS/18 Print LCS.cpp @@ -0,0 +1,46 @@ +#include +using namespace std; + +string LCS(string X, string Y, int n, int m) { + int dp[n + 1][m + 1]; // DP - matrix + + // base case of recursion --> for initialization of dp - matrix + for (int i = 0; i <= n; i++) + for (int j = 0; j <= m; j++) + if (i == 0 || j == 0) + dp[i][j] = 0; + + for (int i = 1; i <= n; i++) + for (int j = 1; j <= m; j++) + if (X[i - 1] == Y[j - 1]) // when last character is same + dp[i][j] = 1 + dp[i - 1][j - 1]; + else // when last character is not same -> pick max + dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]); + + int i = n, j = m; + string lcs = ""; // store charecter when it is equal in the table + while (i > 0 && j > 0) { + if (X[i - 1] == Y[j - 1]) { + lcs += X[i - 1]; // insert in string + i--, j--; + } + else { + if (dp[i][j - 1] > dp[i - 1][j]) + j--; // move to the larger side + else + i--; + } + } + reverse(lcs.begin(), lcs.end()); // at last reverse the string to get LCS + + return lcs; +} + +signed main() { + string X, Y; cin >> X >> Y; + int n = X.length(), m = Y.length(); + + cout << LCS(X, Y, n, m) << endl; + return 0; +} +// https://www.geeksforgeeks.org/printing-longest-common-subsequence/ diff --git a/Data Structures and Algorithm/DP/LCS/19 Shortest Common Supersequence.cpp b/Data Structures and Algorithm/DP/LCS/19 Shortest Common Supersequence.cpp new file mode 100644 index 0000000..2dd0995 --- /dev/null +++ b/Data Structures and Algorithm/DP/LCS/19 Shortest Common Supersequence.cpp @@ -0,0 +1,34 @@ + +#include +using namespace std; + +int LCS(string X, string Y, int n, int m) { + int dp[n + 1][m + 1]; // DP - matrix + + // base case of recursion --> for initialization of dp - matrix + for (int i = 0; i <= n; i++) + for (int j = 0; j <= m; j++) + if (i == 0 || j == 0) + dp[i][j] = 0; + + for (int i = 1; i <= n; i++) + for (int j = 1; j <= m; j++) + if (X[i - 1] == Y[j - 1]) // when last character is same + dp[i][j] = 1 + dp[i - 1][j - 1]; + else // when last character is not same -> pick max + dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]); + + return dp[n][m]; +} + +int SCS(string X, string Y, int n, int m) { + return m + n - LCS(X, Y, n, m); // formula // n-> length of string x ; m-> length of string y +} + +signed main() { + string X, Y; cin >> X >> Y; + int n = X.length(), m = Y.length(); + + cout << SCS(X, Y, n, m) << endl; + return 0; +} diff --git a/Data Structures and Algorithm/DP/LCS/20 Minimum insertion deletion to convert a to b.cpp b/Data Structures and Algorithm/DP/LCS/20 Minimum insertion deletion to convert a to b.cpp new file mode 100644 index 0000000..09de394 --- /dev/null +++ b/Data Structures and Algorithm/DP/LCS/20 Minimum insertion deletion to convert a to b.cpp @@ -0,0 +1,35 @@ +#include +using namespace std; + +int LCS(string X, string Y, int n, int m) { + int dp[n + 1][m + 1]; // DP - matrix + + // base case of recursion --> for initialization of dp - matrix + for (int i = 0; i <= n; i++) + for (int j = 0; j <= m; j++) + if (i == 0 || j == 0) + dp[i][j] = 0; + + for (int i = 1; i <= n; i++) + for (int j = 1; j <= m; j++) + if (X[i - 1] == Y[j - 1]) // when last character is same + dp[i][j] = 1 + dp[i - 1][j - 1]; + else // when last character is not same -> pick max + dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]); + + return dp[n][m]; +} + +void MinInsertDel(string X, string Y, int n, int m) { + int lcs_len = LCS(X, Y, n, m); + cout << "Minimum number of deletions = " << (n - lcs_len)< 0 && j > 0) { + if (X[i - 1] == Y[j - 1]) { // when char are eqaul from table obs + scs += X[i - 1]; // take only once + i--, j--; // and decrement both + } + else if (dp[i][j - 1] > dp[i - 1][j]) { + scs += Y[j - 1]; // in this we will take the charecter to string + j--; + } + else { + scs += X[i - 1]; // taking the charecter to string + i--; + } + } + + while (i > 0) { + scs += X[i - 1]; // take left chareter from str1 + i--; + } + + while (j > 0) { + scs += Y[j - 1]; // take left chareter from str1 + j--; + } + + reverse(scs.begin(), scs.end()); + + return scs; +} + +int main() { + string X, Y; cin >> X >> Y; + int n = X.length(), m = Y.length(); + + cout << SCS(X, Y, n, m) << endl; + return 0; +} diff --git a/Data Structures and Algorithm/DP/LCS/24 Longest repeating subsequence.cpp b/Data Structures and Algorithm/DP/LCS/24 Longest repeating subsequence.cpp new file mode 100644 index 0000000..032bc82 --- /dev/null +++ b/Data Structures and Algorithm/DP/LCS/24 Longest repeating subsequence.cpp @@ -0,0 +1,29 @@ +#include +using namespace std; + +int LCS(string X, string Y, int n, int m) { + int dp[n + 1][m + 1]; // DP - matrix + + for (int i = 0; i <= n; i++) + for (int j = 0; j <= m; j++) + if (i == 0 || j == 0) + dp[i][j] = 0; + + for (int i = 1; i <= n; i++) + for (int j = 1; j <= m; j++) + if (X[i - 1] == Y[j - 1] && i != j) // jsut add an condition that element at ith index should not be equal to jth index + dp[i][j] = 1 + dp[i - 1][j - 1]; + else + dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]); + + return dp[n][m]; +} + +signed main() { + string X; cin >> X; + int n = X.length(); + + cout << LCS(X, X, n, n) << endl; + return 0; +} +// https://www.geeksforgeeks.org/longest-repeating-subsequence/ diff --git a/Data Structures and Algorithm/DP/LCS/25 Sequence pattern matching.cpp b/Data Structures and Algorithm/DP/LCS/25 Sequence pattern matching.cpp new file mode 100644 index 0000000..418adb8 --- /dev/null +++ b/Data Structures and Algorithm/DP/LCS/25 Sequence pattern matching.cpp @@ -0,0 +1,33 @@ +#include +using namespace std; + +int LCS(string X, string Y, int n, int m) { + int dp[n + 1][m + 1]; // DP - matrix + + // base case of recursion --> for initialization of dp - matrix + for (int i = 0; i <= n; i++) + for (int j = 0; j <= m; j++) + if (i == 0 || j == 0) + dp[i][j] = 0; + + for (int i = 1; i <= n; i++) + for (int j = 1; j <= m; j++) + if (X[i - 1] == Y[j - 1]) + dp[i][j] = 1 + dp[i - 1][j - 1]; + else + dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]); + + return dp[n][m]; +} + +bool SeqPatternMatching(string X, string Y, int n, int m) { + return LCS(X, Y, n, m) == min(n, m); // condition to get sequence // if string x is there in y print boolean value according to LCS +} + +signed main() { + string X, Y; cin >> X >> Y; + int n = X.length(), m = Y.length(); + + SeqPatternMatching(X, Y, n, m) ? "YES\n" : "NO\n"; + return 0; +} diff --git a/Data Structures and Algorithm/DP/LCS/26 Minimum Number of insertion to make a string palindrome.cpp b/Data Structures and Algorithm/DP/LCS/26 Minimum Number of insertion to make a string palindrome.cpp new file mode 100644 index 0000000..e97d07b --- /dev/null +++ b/Data Structures and Algorithm/DP/LCS/26 Minimum Number of insertion to make a string palindrome.cpp @@ -0,0 +1,39 @@ +#include +using namespace std; + +int LCS(string X, string Y, int n, int m) { + int dp[n + 1][m + 1]; // DP - matrix + + // base case of recursion --> for initialization of dp - matrix + for (int i = 0; i <= n; i++) + for (int j = 0; j <= m; j++) + if (i == 0 || j == 0) + dp[i][j] = 0; + + for (int i = 1; i <= n; i++) + for (int j = 1; j <= m; j++) + if (X[i - 1] == Y[j - 1]) // when last character is same + dp[i][j] = 1 + dp[i - 1][j - 1]; + else // when last character is not same -> pick max + dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]); + + return dp[n][m]; +} + +int LPS(string X, int n) { + string rev_X = X; + reverse(rev_X.begin(), rev_X.end()); + return LCS(X, rev_X, n, n); +} + +int MinInsertForPallindrome(string X, int n) { + return n - LPS(X, n); // substract LPS from the length of string to get Minimum number of insertion to make a string palindrome +} + +int main() { + string X, Y; cin >> X; + int n = X.length(); + + cout << MinInsertForPallindrome(X, n) << endl; + return 0; +} diff --git a/Data Structures and Algorithm/DP/LCS/longest_common_subsequence.cpp b/Data Structures and Algorithm/DP/LCS/longest_common_subsequence.cpp new file mode 100644 index 0000000..0099b93 --- /dev/null +++ b/Data Structures and Algorithm/DP/LCS/longest_common_subsequence.cpp @@ -0,0 +1,24 @@ +#include +using namespace std; + +int LCS(string X, string Y, int n, int m) { + // base case + if (n == 0 || m == 0) + return 0; + + // choice diagram + // when both string X and Y is having same last char + if (X[n - 1] == Y[m - 1]) + return 1 + LCS(X, Y, n - 1, m - 1); // count the number and decreament the both's string length + // when both string's last character is not same + else + return max(LCS(X, Y, n - 1, m), LCS(X, Y, n, m - 1)); // one take full and another by leaving last and vice versa +} + +int main() { + string X, Y; cin >> X >> Y; + int n = X.length(), m = Y.length(); + + cout << LCS(X, Y, n, m) << endl; + return 0; +} diff --git a/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/37 Egg dropping problem recursive.cpp b/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/37 Egg dropping problem recursive.cpp new file mode 100644 index 0000000..5541008 --- /dev/null +++ b/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/37 Egg dropping problem recursive.cpp @@ -0,0 +1,25 @@ +#include +using namespace std; + +int Solve(int eggs, int floors) { + if (eggs == 1) + return floors; + if (floors == 0 || floors == 1) + return floors; + + int mn = INT_MAX; + for (int k = 1; k <= floors; k++) { + int temp_ans = 1 + max(Solve(eggs - 1, k - 1), Solve(eggs, floors - k)); // once egg break means decrement both floor and egg another agg did not break means check egg dropping from above + mn = min(mn, temp_ans); + } + + return mn; +} + +int main() { + int eggs, floors; + cin >> eggs >> floors; + + cout << Solve(eggs, floors) << endl; + return 0; +} diff --git a/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/38 Egg dropping problem top down.cpp b/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/38 Egg dropping problem top down.cpp new file mode 100644 index 0000000..59da8a4 --- /dev/null +++ b/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/38 Egg dropping problem top down.cpp @@ -0,0 +1,33 @@ +#include +using namespace std; + +const int D = 101; +int t[D][D]; + +int Solve(int eggs, int floors) { + if (t[eggs][floors] != -1) + return t[eggs][floors]; + + if (eggs == 1 || floors == 0 || floors == 1) { + t[eggs][floors] = floors; + return floors; + } + + int mn = INT_MAX; + for (int k = 1; k <= floors; k++) { + int temp_ans = 1 + max(Solve(eggs - 1, k - 1), Solve(eggs, floors - k)); + mn = min(mn, temp_ans); + } + + return t[eggs][floors] = mn; // store in table for further reference +} + +signed main() { + int eggs, floors; + cin >> eggs >> floors; + + memset(t, -1, sizeof(t)); + + cout << Solve(eggs, floors) << endl; + return 0; +} diff --git a/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/39 Egg dropping problem memoization optimization.cpp b/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/39 Egg dropping problem memoization optimization.cpp new file mode 100644 index 0000000..1ec064b --- /dev/null +++ b/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/39 Egg dropping problem memoization optimization.cpp @@ -0,0 +1,47 @@ +#include +using namespace std; + +const int D = 101; +int dp[D][D]; + +int Solve(int eggs, int floors) { + if (dp[eggs][floors] != -1) // if value is already there in the table then return the value + return dp[eggs][floors]; + + if (eggs == 1 || floors == 0 || floors == 1) { // base condition + dp[eggs][floors] = floors; + return floors; + } + + int mn = INT_MAX; + for (int k = 1; k <= floors; k++) { + int top, bottom; + if (dp[eggs - 1][k - 1] != -1) // break the temp in sub problemes + top = dp[eggs - 1][k - 1]; + else { + top = Solve(eggs - 1, k - 1); + dp[eggs - 1][k - 1] = top; + } + + if (dp[eggs][floors - k] != -1) + bottom = dp[eggs][floors - k]; + else { + bottom = Solve(eggs, floors - k); + dp[eggs][floors - k] = bottom; + } + int temp_ans = 1 + max(top, bottom); + mn = min(mn, temp_ans); + } + + return dp[eggs][floors] = mn; +} + +int main() { + int eggs, floors; + cin >> eggs >> floors; + + memset(dp, -1, sizeof(dp)); + + cout << Solve(eggs, floors) << endl; + return 0; +} diff --git a/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/Evaluate Expression to true Recursive.cpp b/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/Evaluate Expression to true Recursive.cpp new file mode 100644 index 0000000..3bd99ce --- /dev/null +++ b/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/Evaluate Expression to true Recursive.cpp @@ -0,0 +1,69 @@ +#include +using namespace std; + +int solve(string s, int i, int j, bool isTrue) +{ + if(i >= j) + { + if(isTrue) + { + return s[i] == 'T'; + } + else + { + return s[i] == 'F'; + } + } + int ans = 0; + for(int k = i + 1; k < j; k += 2) + { + int lT = solve(s, i, k - 1, true); + int lF = solve(s, i, k - 1, false); + int rT = solve(s, k + 1, j, true); + int rF = solve(s, k + 1, j, false); + + if(s[k] == '&') + { + if(isTrue) + { + ans += lT * rT; + } + else + { + ans += lF * rT + lT * rF + lF * rF; + } + } + else if(s[k] == '|') + { + if(isTrue) + { + ans += lT * rT + lT * rF + lF * rT; + } + else + { + ans += lF * rF; + } + } + else if(s[k] == '^') + { + if(isTrue) + { + ans += lF * rT + lT * rF; + } + else + { + ans += lT * rT + lF * rF; + } + } + } + return ans; +} + +int main() +{ + string s; + cout << "Enter String: "; + cin >> s; + cout << solve(s, 0, s.length() - 1, true); + return 0; +} diff --git a/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/Evaluate Expression to true using 3D matrix.cpp b/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/Evaluate Expression to true using 3D matrix.cpp new file mode 100644 index 0000000..bf301b0 --- /dev/null +++ b/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/Evaluate Expression to true using 3D matrix.cpp @@ -0,0 +1,79 @@ +#include +using namespace std; + +int static t[2][1001][1001]; + +int solve(string s, int i, int j, bool isTrue) +{ + if(i >= j) + { + if(isTrue) + { + return s[i] == 'T'; + } + else + { + return s[i] == 'F'; + } + return t[isTrue][i][j]; + } + + if(t[isTrue][i][j] != -1) + { + return t[isTrue][i][j]; + } + int ans = 0; + for(int k = i + 1; k < j; k += 2) + { + int lT = solve(s, i, k - 1, true); + int lF = solve(s, i, k - 1, false); + int rT = solve(s, k + 1, j, true); + int rF = solve(s, k + 1, j, false); + + if(s[k] == '&') + { + if(isTrue) + { + ans += lT * rT; + } + else + { + ans += lF * rT + lT * rF + lF * rF; + } + } + else if(s[k] == '|') + { + if(isTrue) + { + ans += lT * rT + lT * rF + lF * rT; + } + else + { + ans += lF * rF; + } + } + else if(s[k] == '^') + { + if(isTrue) + { + ans += lF * rT + lT * rF; + } + else + { + ans += lT * rT + lF * rF; + } + } + } + return t[isTrue][i][j] = ans; +} + +int main() +{ + string s; + memset(t[0], -1, sizeof(t[0])); + memset(t[1], -1, sizeof(t[1])); + cout << "Enter String: "; + cin >> s; + cout << solve(s, 0, s.length() - 1, true); + return 0; +} diff --git a/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/Evaluate Expression to true using map.cpp b/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/Evaluate Expression to true using map.cpp new file mode 100644 index 0000000..8823e4a --- /dev/null +++ b/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/Evaluate Expression to true using map.cpp @@ -0,0 +1,80 @@ +#include +using namespace std; + +unordered_map mp; + +int solve(string s, int i, int j, bool isTrue) +{ + string temp = to_string(i) + " " + to_string(j) + " " + to_string(isTrue); + + if(mp.find(temp) != mp.end()) + { + return mp[temp]; + } + + if(i >= j) + { + if(isTrue) + { + return s[i] == 'T'; + } + else + { + return s[i] == 'F'; + } + return mp[temp]; + } + int ans = 0; + for(int k = i + 1; k < j; k += 2) + { + int lT = solve(s, i, k - 1, true); + int lF = solve(s, i, k - 1, false); + int rT = solve(s, k + 1, j, true); + int rF = solve(s, k + 1, j, false); + + if(s[k] == '&') + { + if(isTrue) + { + ans += lT * rT; + } + else + { + ans += lF * rT + lT * rF + lF * rF; + } + } + else if(s[k] == '|') + { + if(isTrue) + { + ans += lT * rT + lT * rF + lF * rT; + } + else + { + ans += lF * rF; + } + } + else if(s[k] == '^') + { + if(isTrue) + { + ans += lF * rT + lT * rF; + } + else + { + ans += lT * rT + lF * rF; + } + } + } + return mp[temp] = ans; +} + +int main() +{ + string s; + mp.clear(); + cout << "Enter String: "; + cin >> s; + cout << solve(s, 0, s.length() - 1, true); + return 0; +} diff --git a/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/egg_dropping_recursive.cpp b/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/egg_dropping_recursive.cpp new file mode 100644 index 0000000..27ae0d8 --- /dev/null +++ b/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/egg_dropping_recursive.cpp @@ -0,0 +1,32 @@ +#include +using namespace std; + +int solve(int eggs, int floors) +{ + if(floors == 0 || floors == 1) + { + return floors; + } + if(eggs == 1) + { + return floors; + } + int mn = INT_MAX; + for (int k = 1; k <= floors; ++k) + { + int temp = 1 + max(solve(eggs - 1, k - 1), solve(eggs, floors - k)); + mn = min(mn, temp); + } + return mn; +} + +int main() +{ + int eggs, floors; + cout << "Enter number of eggs: "; + cin >> eggs; + cout << "Enter number of floors: "; + cin >> floors; + cout << solve(eggs, floors); + return 0; +} diff --git a/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/mcm.cpp b/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/mcm.cpp new file mode 100644 index 0000000..4a17160 --- /dev/null +++ b/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/mcm.cpp @@ -0,0 +1,40 @@ +#include +using namespace std; + +int solve(vector &arr, int i, int j) +{ + int mini = INT_MAX; + // Base case + if(i >= j) + { + return 0; + } + + for (int k = i; k <= j - 1 ; k++) + { + int tempAns = solve(arr, i, k) + solve(arr, k + 1, j) + arr[i - 1] * arr[k] * arr[j]; + if(tempAns < mini) + { + mini = tempAns; + } + } + return mini; +} + +int main() +{ + // vector arr = {1, 2, 3, 4, 3}; + vector arr; + int n; + int a; + cout << "Number of element: "; + cin >> n; + for(int i = 0; i < n; i++) + { + cin >> a; + arr.push_back(a); + } + // int n = arr.size(); + cout << "Minimum Number of multiplication is " << solve(arr, 1, n - 1); + return 0; +} diff --git a/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/mcm_using_memo.cpp b/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/mcm_using_memo.cpp new file mode 100644 index 0000000..5aac594 --- /dev/null +++ b/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/mcm_using_memo.cpp @@ -0,0 +1,48 @@ +#include +using namespace std; + +int static t[1001][1001]; + +int solve(vector &arr, int i, int j) +{ + int mini = INT_MAX; + // Base case + if(i >= j) + { + return 0; + } + + if(t[i][j] != -1) + { + return t[i][j]; + } + + for (int k = i; k <= j - 1 ; k++) + { + int tempAns = solve(arr, i, k) + solve(arr, k + 1, j) + arr[i - 1] * arr[k] * arr[j]; + if(tempAns < mini) + { + mini = tempAns; + } + } + return t[i][j] = mini; +} + +int main() +{ + // vector arr = {1, 2, 3, 4, 3}; + vector arr; + memset(t, -1, sizeof(t)); + int n; + int a; + cout << "Number of element: "; + cin >> n; + for(int i = 0; i < n; i++) + { + cin >> a; + arr.push_back(a); + } + // int n = arr.size(); + cout << "Minimum Number of multiplication is " << solve(arr, 1, n - 1); + return 0; +} diff --git a/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/palindrome_partitioning.cpp b/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/palindrome_partitioning.cpp new file mode 100644 index 0000000..b6748fc --- /dev/null +++ b/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/palindrome_partitioning.cpp @@ -0,0 +1,50 @@ +#include +using namespace std; + +bool isPalindrome(string s, int i, int j) +{ + while (i < j) + { + if(s[i] != s[j]) + { + return false; + } + i++; + j--; + } + return true; +} + +int solve(string s, int i, int j) +{ + if(i >= j) + { + return 0; + } + if(isPalindrome(s, i, j) == true) + { + return 0; + } + int mn = INT32_MAX; + for(int k = i; k < j; k++) + { + int temp = 1 + solve(s, i, k) + solve(s, k + 1, j); + if(temp < mn) + { + mn = temp; + } + } + return mn; +} + +int main() +{ + string s; + cout << "Enter a string: "; + cin >> s; + cout << "Min. cuts needed for palindrome partitioning is: " << solve(s, 0, s.length() - 1) << endl; + return 0; +} + +// TC:- O(2^n) +// SC:- O(n) diff --git a/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/palindrome_partitioning_using_memo.cpp b/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/palindrome_partitioning_using_memo.cpp new file mode 100644 index 0000000..22dc042 --- /dev/null +++ b/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/palindrome_partitioning_using_memo.cpp @@ -0,0 +1,81 @@ +#include +using namespace std; + +int static t[1001][1001]; + +bool isPalindrome(string s, int i, int j) +{ + if(i == j) + { + return true; + } + if(i > j) + { + return true; + } + while (i < j) + { + if(s[i] != s[j]) + { + return false; + } + i++; + j--; + } + return true; +} + +int solve(string s, int i, int j) +{ + if(i >= j) + { + return 0; + } + if(isPalindrome(s, i, j) == true) + { + return 0; + } + if(t[i][j] != -1) + { + return t[i][j]; + } + int mn = INT32_MAX; + for(int k = i; k < j; k++) + { + int left, right; + if(t[i][k] != -1) + { + left = t[i][k]; + } + else + { + left = solve(s, i, k); + t[i][k] = left; + } + if(t[k+1][j] != -1) + { + right = t[k+1][j]; + } + else + { + right = solve(s, k + 1, j); + t[k+1][j] = right; + } + int temp = 1 + left + right; + if(temp < mn) + { + mn = temp; + } + } + return t[i][j] = mn; +} + +int main() +{ + string s; + memset(t, -1, sizeof(t)); + cout << "Enter a string: "; + cin >> s; + cout << "Min. cuts needed for palindrome partitioning is: " << solve(s, 0, s.length() - 1) << endl; + return 0; +} diff --git a/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/scrambled_string_memoized.cpp b/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/scrambled_string_memoized.cpp new file mode 100644 index 0000000..bb13443 --- /dev/null +++ b/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/scrambled_string_memoized.cpp @@ -0,0 +1,51 @@ + #include + using namespace std; + + unordered_map mp; + + bool solve(string a, string b) + { + string key = a + " " + b; + if(a.compare(b) == 0) + { + return true; + } + if(a.length() <= 1) + { + return false; + } + if(mp.find(key) != mp.end()) + { + return mp[key]; + } + int n = a.length(); + bool flag = false; + for(int i = 1; i < n; i++) + { + if ((solve(a.substr(0, i), b.substr(n - i, i)) && solve(a.substr(i), b.substr(0, n - i))) || (solve(a.substr(0, i), b.substr(0, i)) && solve(a.substr(i), b.substr(i)))) + { + flag = true; + break; + } + } + + return mp[key] = flag; + } + + int main() + { + string a, b; + cout << "Enter first string: "; + cin >> a; + cout << "Enter secon string: "; + cin >> b; + if(a.length() != b.length()) + { + cout << "NO" << endl; + } + else + { + solve(a, b) ? cout << "YES" << endl : cout << "NO" << endl; + } + return 0; + } diff --git a/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/scrambled_string_recursive.cpp b/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/scrambled_string_recursive.cpp new file mode 100644 index 0000000..e116ee8 --- /dev/null +++ b/Data Structures and Algorithm/DP/Matrix_Chain_Multiplication/scrambled_string_recursive.cpp @@ -0,0 +1,44 @@ + #include + using namespace std; + + bool solve(string a, string b) + { + if(a.compare(b) == 0) + { + return true; + } + if(a.length() <= 1) + { + return false; + } + int n = a.length(); + bool flag = false; + for(int i = 1; i < n; i++) + { + if ((solve(a.substr(0, i), b.substr(n - i, i)) && solve(a.substr(i), b.substr(0, n - i))) || (solve(a.substr(0, i), b.substr(0, i)) && solve(a.substr(i), b.substr(i)))) + { + flag = true; + break; + } + } + + return flag; + } + + int main() + { + string a, b; + cout << "Enter first string: "; + cin >> a; + cout << "Enter secon string: "; + cin >> b; + if(a.length() != b.length()) + { + cout << "NO" << endl; + } + else + { + solve(a, b) ? cout << "YES" << endl : cout << "NO" << endl; + } + return 0; + } diff --git a/Data Structures and Algorithm/DP/Travelling_salesman.cpp b/Data Structures and Algorithm/DP/Travelling_salesman.cpp new file mode 100644 index 0000000..d3034b5 --- /dev/null +++ b/Data Structures and Algorithm/DP/Travelling_salesman.cpp @@ -0,0 +1,66 @@ +#include +using namespace std; + +int tsp(vector> dist, int setOfCities, int city, int n) +{ + if(setOfCities == ((1<> dist, int setOfCities, int city, int n, vector> &dp) +{ + if(setOfCities == (1 << n) - 1) + { + return dist[city][0]; + } + if(dp[setOfCities][city] != -1) + { + return dp[setOfCities][city]; + } + + int ans = INT_MAX; + + for(int choice = 0; choice < n; choice++) + { + if((setOfCities & (1 << choice)) == 0) + { + int subProb = dist[city][choice] + tspDP(dist, setOfCities | (1 << choice), choice, n, dp); + ans = min(ans, subProb); + } + } + dp[setOfCities][city] = ans; + return ans; +} + +int main() +{ + vector> dist = { + {0, 20, 42, 25}, + {20, 0, 30, 34}, + {42, 30, 0, 10}, + {25, 34, 10, 0}, + }; + int n = 4; + vector> dp(1 << n, vector(n, -1)); + cout << tspDP(dist, 1, 0, n, dp) << endl; + return 0; +}