diff --git a/DynamicProgramming/01Knapsack.cpp b/DynamicProgramming/01Knapsack.cpp new file mode 100644 index 0000000..378c780 --- /dev/null +++ b/DynamicProgramming/01Knapsack.cpp @@ -0,0 +1,29 @@ +/* +Given two integer arrays A and B of size N each which represent values and weights associated with N items respectively. + +Also given an integer C which represents knapsack capacity. + +Find out the maximum value subset of A such that sum of the weights of this subset is smaller than or equal to C. + +NOTE: +You cannot break an item, either pick the complete item, or don’t pick it (0-1 property). +*/ +int Solution::solve(vector &A, vector &B, int C) { + int n=A.size(); + int m=B.size(); + vector>dp(n+1,vector(C+1,0)); + for(int i=1;i<=n;i++)dp[i][0]=0; + for(int i=1;i<=C;i++) dp[0][i]=0; + for(int i=1;i<=n;i++) + { + for(int j=1;j<=C;j++) + { + dp[i][j]=dp[i-1][j]; + if(j>=B[i-1]) + { + dp[i][j]=max(dp[i][j], A[i-1] +dp[i-1][j-B[i-1]]); + } + } + } + return dp[n][C]; +} diff --git a/DynamicProgramming/Arrange.cpp b/DynamicProgramming/Arrange.cpp new file mode 100644 index 0000000..c727000 --- /dev/null +++ b/DynamicProgramming/Arrange.cpp @@ -0,0 +1,35 @@ +/*You are given a sequence of black and white horses, and a set of K stables numbered 1 to K. You have to accommodate the horses into the stables in such a way that the following conditions are satisfied: + +You fill the horses into the stables preserving the relative order of horses. For instance, you cannot put horse 1 into stable 2 and horse 2 into stable 1. You have to preserve the ordering of the horses. +No stable should be empty and no horse should be left unaccommodated. +Take the product (number of white horses * number of black horses) for each stable and take the sum of all these products. This value should be the minimum among all possible accommodation arrangements*/ + +int solve(int i,int k,int n,string A, vector>&t) +{ + if(i>=n && k>0) return INT_MAX/2; + if(t[i][k]!=-1) return t[i][k]; + int w=0,b=0; + if(k==1) + { + for(int j=i;jA.size()) return -1; + vector>t(A.size()+1,vector(B+1,-1)); + return solve(0,B,A.size(),A,t); +} diff --git a/DynamicProgramming/BestTimeToBuy&SellStockAtmostBTimes.cpp b/DynamicProgramming/BestTimeToBuy&SellStockAtmostBTimes.cpp new file mode 100644 index 0000000..589e3ba --- /dev/null +++ b/DynamicProgramming/BestTimeToBuy&SellStockAtmostBTimes.cpp @@ -0,0 +1,22 @@ +/*Given an array of integers A of size N in which ith element is the price of the stock on day i. + +You can complete atmost B transactions. + +Find the maximum profit you can achieve. + +NOTE: You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).*/ +int Solution::solve(vector &A, int B) { + int n=A.size(); + B=min(B,n/2); + vector>dp(n,vector(B+1,0)); + for(int j=1;j<=B;j++) + { + int prev=INT_MIN; + for(int i=1;i > &A) { + int n=A.size(); + vectordp(n,1); + int ans=1; + for(int i=0;iA[j][1]) + { + dp[i]=max(dp[i],dp[j]+1); + } + ans=max(ans,dp[i]); + } + } + return ans; +} diff --git a/DynamicProgramming/CoinSumInfinite.cpp b/DynamicProgramming/CoinSumInfinite.cpp new file mode 100644 index 0000000..bb86350 --- /dev/null +++ b/DynamicProgramming/CoinSumInfinite.cpp @@ -0,0 +1,18 @@ +/*You are given a set of coins S. In how many ways can you make sum N assuming you have infinite amount of each coin in the set. + +Note : Coins in set S will be unique. Expected space complexity of this problem is O(N).*/ + +int Solution::coinchange2(vector &A, int B) { + int n=A.size(); + vectordp(B+1,0); + dp[0]=1; + sort(A.begin(),A.end()); + for(int i=0;i&A,vector>&dp) +{ + if(start==end) return dp[start][end]=A[end]; + if(dp[start][end]!=-1) return dp[start][end]; + int res=max(A[start]-ans(start+1,end,A,dp), A[end]-ans(start,end-1,A,dp)); + return dp[start][end]=res; +} +int Solution::maxcoin(vector &A) { + int n=A.size(); + vector>dp(n,vector(n,-1)); + ans(0,A.size()-1,A,dp); + int sum=0; + for(int i=0;i>dp(n+1,vector(m+1,0)); + for(int i=0;i<=n;i++) + { + dp[i][0]=1; + } + for(int i=1;i<=m;i++) + { + dp[0][i]=0; + } + for(int i=1;i<=n;i++) + { + for(int j=1;j<=m;j++) + { + if(A[i-1]==B[j-1]) + { + dp[i][j]=dp[i-1][j]+dp[i-1][j-1]; + } + else + { + dp[i][j]=dp[i-1][j]; + } + } + } + return dp[n][m]; +} diff --git a/DynamicProgramming/DungeonPrincess.cpp b/DynamicProgramming/DungeonPrincess.cpp new file mode 100644 index 0000000..50fa9fe --- /dev/null +++ b/DynamicProgramming/DungeonPrincess.cpp @@ -0,0 +1,22 @@ +/*The demons had captured the princess (P) and imprisoned her in the bottom-right corner of a dungeon. The dungeon consists of M x N rooms laid out in a 2D grid. Our valiant knight (K) was initially positioned in the top-left room and must fight his way through the dungeon to rescue the princess. + +The knight has an initial health point represented by a positive integer. If at any point his health point drops to 0 or below, he dies immediately. + +Some of the rooms are guarded by demons, so the knight loses health (negative integers) upon entering these rooms; other rooms are either empty (0’s) or contain magic orbs that increase the knight’s health (positive integers). + +In order to reach the princess as quickly as possible, the knight decides to move only rightward or downward in each step. +*/ +int Solution::calculateMinimumHP(vector > &A) { + int r=A.size(),c=A[0].size(); + for(int i=r-1;i>=0;i--) + { + for(int j=c-1;j>=0;j--) + { + if(i==r-1&&j==c-1) A[i][j]=max(1-A[i][j],1); + else if(j==c-1) A[i][j]=max(A[i+1][j]-A[i][j],1); + else if(i==r-1) A[i][j]=max(A[i][j+1]-A[i][j],1); + else A[i][j]=max(min(A[i+1][j],A[i][j+1])-A[i][j],1); + } + } + return A[0][0]; +} diff --git a/DynamicProgramming/EditDistance.cpp b/DynamicProgramming/EditDistance.cpp new file mode 100644 index 0000000..d79155e --- /dev/null +++ b/DynamicProgramming/EditDistance.cpp @@ -0,0 +1,34 @@ +/* +Given two strings A and B, find the minimum number of steps required to convert A to B. (each operation is counted as 1 step.) + +You have the following 3 operations permitted on a word: + +Insert a character +Delete a character +Replace a character +*/ +int Solution::minDistance(string A, string B) { + int n=A.size(); + int m=B.size(); + vector>dp(n+1,vector(m+1,INT_MAX)); + for(int i=0;i<=n;i++) + { + for(int j=0;j<=m;j++) + { + if(i==0 || j==0) + { + if(i==0) dp[i][j]=j; // need to delete all char of one string to make it equal to 0 + else dp[i][j]=i; // need to insert... + } + else if(A[i-1]==B[j-1]) + { + dp[i][j]=dp[i-1][j-1]; // same char. no need of operation + } + else + { + dp[i][j]=1+min(dp[i-1][j],min(dp[i][j-1],dp[i-1][j-1])); + } + } + } + return dp[n][m]; +} diff --git a/DynamicProgramming/FlipArray.cpp b/DynamicProgramming/FlipArray.cpp new file mode 100644 index 0000000..b839fcb --- /dev/null +++ b/DynamicProgramming/FlipArray.cpp @@ -0,0 +1,37 @@ +/* +Given an array of positive elements, you have to flip the sign of some of its elements such that the resultant sum of the elements of array should be minimum non-negative(as close to zero as possible). Return the minimum no. of elements whose sign needs to be flipped such that the resultant sum is minimum non-negative. +*/ +int Solution::solve(const vector &A) { +int n = A.size(); +int sumv = 0; +for(int i=0;i > dp(n+1,vector(req+1,INT_MAX)); +dp[0][0] = 0; +for(int i=0;i<=n;i++) +{ + dp[i][0] = 0; +} +for(int i=1;i<=n;i++) +{ + for(int j=1;j<=req;j++) + { + int a=INT_MAX; + int b; + if(j>=A[i-1]) + { + a = dp[i-1][j-A[i-1]]; + if(a!=INT_MAX) a+=1; + } + b = dp[i-1][j]; + dp[i][j] = min(a,b); + } +} +for(int i=req;i>=0;i--){ + if(dp[n][i]!=INT_MAX){ + return dp[n][i]; + } +} +} diff --git a/DynamicProgramming/IncreasingPathInMatrix.cpp b/DynamicProgramming/IncreasingPathInMatrix.cpp new file mode 100644 index 0000000..b40f70c --- /dev/null +++ b/DynamicProgramming/IncreasingPathInMatrix.cpp @@ -0,0 +1,47 @@ +/*Given a 2D integer matrix A of size N x M. + +From A[i][j] you can move to A[i+1][j], if A[i+1][j] > A[i][j], or can move to A[i][j+1] if A[i][j+1] > A[i][j]. + +The task is to find and output the longest path length if we start from (0, 0). + +NOTE: + +If there doesn't exist a path return -1.*/ +int Solution::solve(vector > &A) { + int n=A.size(); + int m=A[0].size(); + vector>dp(n,vector(m,0)); + int ans=-1; + dp[0][0]=1; + for(int i=0;iA[i][j-1] && dp[i][j-1]!=0) + dp[i][j]=1+dp[i][j-1]; + } + else + { + if(A[i][j]>A[i-1][j] && dp[i-1][j]!=0) + dp[i][j]=1+dp[i-1][j]; + } + } + else + { + if(A[i][j]>A[i-1][j] && dp[i-1][j]!=0) + dp[i][j]=max(dp[i][j],1+dp[i-1][j]); + if(A[i][j]>A[i][j-1] && dp[i][j-1]!=0) + { + dp[i][j]=max(dp[i][j],1+dp[i][j-1]); + } + } + } + } + if(dp[n-1][m-1]==0) return -1; + return dp[n-1][m-1]; +} diff --git a/DynamicProgramming/InterleavingStrings.cpp b/DynamicProgramming/InterleavingStrings.cpp new file mode 100644 index 0000000..987c23c --- /dev/null +++ b/DynamicProgramming/InterleavingStrings.cpp @@ -0,0 +1,42 @@ +//Given A, B, C, find whether C is formed by the interleaving of A and B. + +int Solution::isInterleave(string A, string B, string C) { + int n=A.size(); + int m=B.size(); + vector>dp(n+1,vector(m+1,false)); + for(int i=0;i<=n;i++) + { + for(int j=0;j<=m;j++) + { + if(i==0 && j==0) + { + dp[i][j]=true; + } + else if(i==0) + { + if(B[j-1]==C[i+j-1]) + dp[i][j]=dp[i][j-1]; + } + else if(j==0) + { + if(A[i-1]==C[i+j-1]) + { + dp[i][j]=dp[i-1][j]; + } + } + else if(A[i-1]==C[i+j-1] && B[j-1]!=C[i+j-1]) + { + dp[i][j]=dp[i-1][j]; + } + else if(B[j-1]==C[i+j-1] && A[i-1]!=C[i+j-1]) + { + dp[i][j]=dp[i][j-1]; + } + else if(C[i+j-1]==B[j-1] && C[i+j-1]==A[i-1]) + { + dp[i][j]=dp[i-1][j] || dp[i][j-1]; + } + } + } + return dp[n][m]; +} diff --git a/DynamicProgramming/IntersectingChordsInCircles.cpp b/DynamicProgramming/IntersectingChordsInCircles.cpp new file mode 100644 index 0000000..51b9e7b --- /dev/null +++ b/DynamicProgramming/IntersectingChordsInCircles.cpp @@ -0,0 +1,17 @@ +int Solution::chordCnt(int A) +{ +long long int m = 1000000007; +long long int dp[A+1]; +dp[0] = 1; +dp[1]=1; +for(long long int i=2;i<=A;i++) +{ + dp[i] = 0; + for(long long int j=0;j &A) { + int maxindex=0; + if(A.size()==1) return 1; + for(int i=0;i=maxindex) return 0; + if(maxindex >= A.size()-1) return 1; + } + return 0; +} diff --git a/DynamicProgramming/KingdomWar.cpp b/DynamicProgramming/KingdomWar.cpp new file mode 100644 index 0000000..6f96766 --- /dev/null +++ b/DynamicProgramming/KingdomWar.cpp @@ -0,0 +1,36 @@ +/*Two kingdoms are on a war right now, kingdom X and kingdom Y. As a war specialist of kingdom X, you scouted kingdom Y area. + +A kingdom area is defined as a N x M grid with each cell denoting a village. +Each cell has a value which denotes the strength of each corresponding village. +The strength can also be negative, representing those warriors of your kingdom who were held hostages. + +There’s also another thing to be noticed. + +The strength of any village on row larger than one (2<=r<=N) is stronger or equal to the strength of village which is exactly above it. +The strength of any village on column larger than one (2<=c<=M) is stronger or equal to the strength of vilage which is exactly to its left. +(stronger means having higher value as defined above). +So your task is, find the largest sum of strength that you can erase by bombing one sub-matrix in the grid.*/ + +int Solution::solve(vector > &A) { + int n=A.size(); + int m=A[0].size(); + for(int i=0;i=0;j--){ + A[i][j]+=sum; + sum=A[i][j]; + } + } + int ans=A[n-1][m-1]; + for(int i=0;i=0;j--){ + A[j][i]+=sum; + sum=A[j][i]; + mx=max(mx,sum); + } + ans=max(ans,mx); + } + return ans; +} diff --git a/DynamicProgramming/LengthOfLongestBitonicSubsequence.cpp b/DynamicProgramming/LengthOfLongestBitonicSubsequence.cpp new file mode 100644 index 0000000..d8ea786 --- /dev/null +++ b/DynamicProgramming/LengthOfLongestBitonicSubsequence.cpp @@ -0,0 +1,32 @@ +/*Given an 1D integer array A of length N, find the length of longest subsequence which is first increasing then decreasing.*/ +int Solution::longestSubsequenceLength(const vector &A) { + int n=A.size(); + vectorinc(n,1); + vectordec(n,1); + for(int i=0;iA[j]) + { + inc[i]=max(inc[i],inc[j]+1); + } + } + } + for(int i=n-1;i>=0;i--) + { + for(int j=n-1;j>i;j--) + { + if(A[i]>A[j]) + { + dec[i]=max(dec[i],dec[j]+1); + } + } + } + int ans=0; + for(int i=0;i &arr) { + int n = arr.size(), res = 2; + if(n <= 2) + return n; + vector> dp(n); //(key, value) => (position, difference) + for(int i=0; i 0 ? dp[j][diff] + 1 : 2; + res = max(res, dp[i][diff]); + } + } + return res; +} diff --git a/DynamicProgramming/LongestCommonSubsequence.cpp b/DynamicProgramming/LongestCommonSubsequence.cpp new file mode 100644 index 0000000..5712103 --- /dev/null +++ b/DynamicProgramming/LongestCommonSubsequence.cpp @@ -0,0 +1,18 @@ +void LCS(string a,string b){ + int n = a.size(); + int m = b.size(); + vector>dp(n+1,vector(m+1,)); + for(int i = 0;i <= n;i++){ + for(int j = 0; j <= m;j++){ + if(i == 0 || j == 0){ + dp[i][j] = 0; + } + else if(a[i - 1] == b[j - 1]){ + dp[i][j] = dp[i-1][j-1] + 1; + } + else + dp[i][j] = max(dp[i-1][j], dp[i][j-1]); + } + } + return dp[n][m]; +} diff --git a/DynamicProgramming/LongestIncreasingSubsequence.cpp b/DynamicProgramming/LongestIncreasingSubsequence.cpp new file mode 100644 index 0000000..56d5c62 --- /dev/null +++ b/DynamicProgramming/LongestIncreasingSubsequence.cpp @@ -0,0 +1,19 @@ +int Solution::lis(const vector &A) { + int n=A.size(); + vectord(n+1,INT_MAX); + d[0]=INT_MIN; + for(int i=0;id[j-1] && A[i]>dp(A.size(),vector(A.size(),0)); + int res=1; + for(int i=0;is; + int maxlen=0; + s.push(-1); + for(int i=0;i &A) { + int minforward=INT_MIN; + int maxbackward=INT_MIN; + int prod=1; + bool iszero=false; + for(int i=0;i=0;i--) + { + prod*=A[i]; + if(prod==0) + { + iszero=true; + prod=1; + continue; + } + maxbackward=max(maxbackward,prod); + } + if(iszero) return max(0,max(minforward,maxbackward)); + return max(maxbackward,minforward); +} diff --git a/DynamicProgramming/MaxRectangleInBinaryMatrix.cpp b/DynamicProgramming/MaxRectangleInBinaryMatrix.cpp new file mode 100644 index 0000000..88fd6ca --- /dev/null +++ b/DynamicProgramming/MaxRectangleInBinaryMatrix.cpp @@ -0,0 +1,51 @@ +/*Given a 2D binary matrix filled with 0’s and 1’s, find the largest rectangle containing all ones and return its area.*/ +int Solution::maximalRectangle(vector > &A) { + int n=A.size(); + int m=A[0].size(); + vectorheights(m,0); + vectorleft(m,0); + vectorright(m,m-1); + int ans=0; + for(int i=0;i=0;j--) + { + if(A[i][j]==1) + { + right[j]=min(right[j],curr_right); + } + else + { + right[j]=m; + curr_right=j-1; + } + } + for(int j=0;jleft,ans); + int r=help(A->right,ans); + int sum=max(max(l,r)+A->val,A->val); + int max_top=max(sum,l+r+A->val); + ans=max(ans,max_top); + return sum; + } +int Solution::maxPathSum(TreeNode* A) { + int ans=INT_MIN; + help(A,ans); + return ans; +} diff --git a/DynamicProgramming/MaxSumWithoutAdjacent.cpp b/DynamicProgramming/MaxSumWithoutAdjacent.cpp new file mode 100644 index 0000000..958e2d3 --- /dev/null +++ b/DynamicProgramming/MaxSumWithoutAdjacent.cpp @@ -0,0 +1,14 @@ +/*Given a 2 x N grid of integer, A, choose numbers such that the sum of the numbers +is maximum and no two chosen numbers are adjacent horizontally, vertically or diagonally, and return it.*/ +int Solution::adjacent(vector > &A) { + int n=A.size(); + vector>dp(n,vector(2,0)); + dp[0][0]=0; + dp[0][1]=max(A[0][0],A[1][0]); + for(int i=1;i > &A) { + int n=A.size()-1; + for(int i=n-2;i>=0;i--) + { + for(int j=0;j > &A) { + int n=A.size(); + int m=A[0].size(); + int ans=0; + vector>dp(n,vector(m,0)); + for(int i=0;i &A) { + int n=A.size(); + vector>dp(n,vector(n,0)); + vectorprefix_sum(n,0); + prefix_sum[0]=A[0]; + for(int i=1;i &A) { + int n=A.size(); + int furthest=0; + int end=0; + int jumps=0; + if(n==1||n==0)return 0; + if(A[0]==0) return -1; + for(int i=0;i > &triangle) { + // Do not write main() function. + // Do not read input, instead use the arguments to the function. + // Do not print the output, instead return values as specified + // Still have a doubt. Checkout www.interviewbit.com/pages/sample_codes/ for more details + + int n=triangle.size(); + for(int i=n-2;i>=0;i--) + { + for(int j=0;j &A) { + int n=A.size(); + if(n==1) return A[0]; + int sum=0; + for(int i=0;i>dp(n+1,vector(sum/2+1,false)); + for(int i=1;i<=n;i++) dp[i][0]=true; + for(int i=1;i<=sum/2;i++) dp[0][i]=false; + for(int i=1;i<=n;i++) + { + for(int j=1;j<=sum/2;j++) + { + dp[i][j]=dp[i-1][j]; + if(j>=A[i-1]) + { + dp[i][j]=dp[i][j]||dp[i-1][j-A[i-1]]; + } + } + } + int minval=INT_MAX; + for(int i=1;i<=sum/2;i++) + { + if(dp[n][i]) + { + minval=min(minval,abs(sum-2*i)); + } + } + return minval; +} diff --git a/DynamicProgramming/MinSumPath.cpp b/DynamicProgramming/MinSumPath.cpp new file mode 100644 index 0000000..b618da1 --- /dev/null +++ b/DynamicProgramming/MinSumPath.cpp @@ -0,0 +1,22 @@ +int Solution::minPathSum(vector > &A) { + int n=A.size(); + int m=A[0].size(); + vector>dp(n,vector(m,0)); + dp[0][0]=A[0][0]; + for(int i=1;i > &A) { + int n=A.size(); + for(int i=n-2;i>=0;i--) + { + for(int j=0;j<3;j++) + { + A[i][j]+=min(A[i+1][(j+1)%3],A[i+1][(j+2)%3]); + } + } + return min(A[0][0],min(A[0][1],A[0][2])); +} diff --git a/DynamicProgramming/PalindromePartition.cpp b/DynamicProgramming/PalindromePartition.cpp new file mode 100644 index 0000000..29f50f5 --- /dev/null +++ b/DynamicProgramming/PalindromePartition.cpp @@ -0,0 +1,46 @@ +/*Given a string A, partition A such that every substring of the partition is a palindrome. + +Return the minimum cuts needed for a palindrome partitioning of A.*/ +int Solution::minCut(string s) { + int n=s.size(); + vectorc(n,INT_MAX); + vector>p(n,vector(n,0)); + for(int i=0;i>dp(n+1,vector(m+1,false)); + dp[0][0]=true; + for(int i=1;i<=m;i++) + { + if(B[i-1]=='*') + { + dp[0][i]=dp[0][i-1]; + } + } + for(int i=1;i<=n;i++) + { + for(int j=1;j<=m;j++) + { + if(B[j-1]=='*') + { + dp[i][j]=dp[i][j-1] || dp[i-1][j]; + } + else if(B[j-1]=='?' || A[i-1]==B[j-1]) + { + dp[i][j]=dp[i-1][j-1]; + } + } + } + return dp[n][m]; +} diff --git a/DynamicProgramming/RepeatingSubsequence.cpp b/DynamicProgramming/RepeatingSubsequence.cpp new file mode 100644 index 0000000..967de29 --- /dev/null +++ b/DynamicProgramming/RepeatingSubsequence.cpp @@ -0,0 +1,34 @@ +/* +Given a string A, find length of the longest repeating sub-sequence such that the two subsequence don’t have same string character at same position, + +i.e., any i’th character in the two subsequences shouldn’t have the same index in the original string. + +NOTE: Sub-sequence length should be greater than or equal to 2 +*/ +int Solution::anytwo(string A) { + vector>dp(A.size()+1,vector(A.size()+1,0)); + int res=-1; + for(int i=0;i<=A.size();i++) + { + for(int j=0;j<=A.size();j++) + { + dp[i][j]=0; + } + } + for(int i=1;i<=A.size();i++) + { + for(int j=1;j<=A.size();j++) + { + if(A[i-1]==A[j-1] && i!=j) + { + dp[i][j]=dp[i-1][j-1]+1; + } + else + { + dp[i][j]=max(dp[i-1][j],dp[i][j-1]); + } + } + } + if(dp[A.size()][A.size()]>=2) return 1; + return 0; +} diff --git a/DynamicProgramming/ScrambleString.cpp b/DynamicProgramming/ScrambleString.cpp new file mode 100644 index 0000000..d64290d --- /dev/null +++ b/DynamicProgramming/ScrambleString.cpp @@ -0,0 +1,81 @@ +/* +Given a string A, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively. + +Below is one possible representation of A = “great”: + + + great + / \ + gr eat + / \ / \ +g r e at + / \ + a t + +To scramble the string, we may choose any non-leaf node and swap its two children. + +For example, if we choose the node “gr” and swap its two children, it produces a scrambled string “rgeat”. + + rgeat + / \ + rg eat + / \ / \ +r g e at + / \ + a t +We say that “rgeat” is a scrambled string of “great”. + +Similarly, if we continue to swap the children of nodes “eat” and “at”, it produces a scrambled string “rgtae”. + + rgtae + / \ + rg tae + / \ / \ +r g ta e + / \ + t a +We say that “rgtae” is a scrambled string of “great”. + +Given two strings A and B of the same length, determine if B is a scrambled string of S. +*/ + +mapmp; +int Solution::isScramble(const string a, const string b) { + string key = a + " " + b; + if(mp.find(key)!=mp.end()) + return mp[key]; + + if(a==b) + return true; + + if(a.length()<=1) + return false; + + int n=a.length(); + + for(int i=1;i<=n-1;i++) + { + string A1 = a.substr(0,i); + string A2 = a.substr(i,n-i); + string B11 = b.substr(0,i); + string B12 = b.substr(i,n-i); + string B21 = b.substr(0,n-i); + string B22 = b.substr(n-i,i); + + int cont1 = mp[A1+" "+B11] = (mp.find(A1+" "+B11)!=mp.end() ? mp[A1+" "+B11] : isScramble(A1,B11)); + int cont2 = mp[A2+" "+B12] = (mp.find(A2+" "+B12)!=mp.end() ? mp[A2+" "+B12] : isScramble(A2,B12)); + int cont3 = mp[A1+" "+B22] = (mp.find(A1+" "+B22)!=mp.end() ? mp[A1+" "+B22] : isScramble(A1,B22)); + int cont4 = mp[A2+" "+B21] = (mp.find(A2+" "+B21)!=mp.end() ? mp[A2+" "+B21] : isScramble(A2,B21)); + if ((cont1 && cont2) || (cont3 && cont4)) + { + return mp[key]=true; + } + } + return mp[key]=false; +} + + + + + + diff --git a/DynamicProgramming/SmallestSequenceWithPrimes.cpp b/DynamicProgramming/SmallestSequenceWithPrimes.cpp new file mode 100644 index 0000000..c9c3ff8 --- /dev/null +++ b/DynamicProgramming/SmallestSequenceWithPrimes.cpp @@ -0,0 +1,33 @@ +/* +GIven three prime numbers A, B and C and an integer D. + +You need to find the first(smallest) D integers which only have A, B, C or a combination of them as their prime factors. +*/ +vector Solution::solve(int A, int B, int C, int D) { + vectorans; + int i1=0; + int i2=0; + int i3=0; + int next_A=A; + int next_B=B; + int next_C=C; + vectordp(D); + for(int i=0;i&A) +{ + int ans=0; + mapm; + m[0]=1; + int sum=0; + for(int i=0;i > &A) { + int n=A.size(); + if(n==0) return 0; + int m=A[0].size(); + int count=0; + for(int left=0;lefttemp(n,0); + for(int right=left;right &A, int B) { + int n=A.size(); + vector>dp(n+1,vector(B+1,false)); + for(int i=1;i<=B;i++) + { + dp[0][i]=false; + } + for(int i=0;i<=n;i++) + { + dp[i][0]=true; + } + for(int i=1;i<=n;i++) + { + for(int j=1;j<=B;j++) + { + dp[i][j]=dp[i-1][j]; + if(j>=A[i-1]) + { + dp[i][j]=dp[i][j]||dp[i-1][j-A[i-1]]; + } + } + } + return dp[n][B]; +} diff --git a/DynamicProgramming/TilingWithDominos.cpp b/DynamicProgramming/TilingWithDominos.cpp new file mode 100644 index 0000000..3bfed71 --- /dev/null +++ b/DynamicProgramming/TilingWithDominos.cpp @@ -0,0 +1,20 @@ +/*Problem Description + +Given an integer A you have to find the number of ways to fill a 3 x A board with 2 x 1 dominoes. + +Return the answer modulo 109 + 7 . + +*/ +int Solution::solve(int A) +{ + if(A%2) return 0; + vector a(A+1, 0), c(A+1,0); + a[1]=1, c[1]=0, a[2]=0, c[2]=3; + + for(int i=3;i<=A;i++) + { + c[i]=(2*a[i-1]+c[i-2])%1000000007; + a[i]=(c[i-1]+a[i-2])%1000000007; + } + return c[A]; +} diff --git a/DynamicProgramming/TusharsBirthday.cpp b/DynamicProgramming/TusharsBirthday.cpp new file mode 100644 index 0000000..138291f --- /dev/null +++ b/DynamicProgramming/TusharsBirthday.cpp @@ -0,0 +1,37 @@ +/* +As it is Tushar’s Birthday on March 1st, he decided to throw a party to all his friends at TGI Fridays in Pune. +Given are the eating capacity of each friend, filling capacity of each dish and cost of each dish. A friend is satisfied if the sum of the filling capacity of dishes he ate is equal to his capacity. Find the minimum cost such that all of Tushar’s friends are satisfied (reached their eating capacity). + +NOTE: + +Each dish is supposed to be eaten by only one person. Sharing is not allowed. +Each friend can take any dish unlimited number of times. +There always exists a dish with filling capacity 1 so that a solution always exists. +*/ +int Solution::solve(const vector &a, const vector &b, const vector &c) { +int maxi = *max_element(a.begin(),a.end()); + vector >dp(b.size()+1,vector(maxi+1,INT_MAX)); + for(int i=0;i<=b.size();i++){ + dp[i][0] = 0; + } + for(int i=1;i<=maxi;i++){ + if(i % b[0] == 0){ + dp[1][i] = (i/b[0])*c[0]; + } +} + for(int i=2;i<=b.size();i++){ + for(int j=1;j<=maxi;j++){ + if(b[i-1] > j){ + dp[i][j] = dp[i-1][j]; + } + else { + dp[i][j] = min(dp[i-1][j],min((c[i-1]+dp[i-1][j-b[i-1]]),(c[i-1]+dp[i][j-b[i-1]]))); + } + } +} + int sum=0; + for(int i=0;idp(n+1,0); + dp[0]=1; + dp[1]=1; + for(int i=2;i<=A;i++) + { + for(int j=0;j > &A) { + int m=A.size(); + int n=A[0].size(); + vector>dp(m,vector(n,0)); + bool flag=false; + for(int i=0;i 1 + 'B' -> 2 + ... + 'Z' -> 26 +Given an encoded message A containing digits, determine the total number of ways to decode it modulo 109 + 7. +*/ + +int Solution::numDecodings(string s) { + int n=s.size(); + vectorcount(n+1,0); + if(n==0) return 0; + if(s[0]=='0') return 0; + count[0]=1; + count[1]=1; + for(int i=2;i<=n;i++) + { + if(s[i-1]>'0') + { + count[i]=count[i-1]; + } + if(s[i-2]=='1' || s[i-2]=='2' && s[i-1]<'7') + { + count[i]=(count[i]%1000000007+count[i-2]%1000000007)%1000000007; + } + } + return count[n]%1000000007; +} diff --git a/DynamicProgramming/WordBreak.cpp b/DynamicProgramming/WordBreak.cpp new file mode 100644 index 0000000..60457cc --- /dev/null +++ b/DynamicProgramming/WordBreak.cpp @@ -0,0 +1,30 @@ +/* +Given a string A and a dictionary of words B, determine if A can be segmented into a space-separated sequence of one or more dictionary words. +*/ +int Solution::wordBreak(string A, vector &B) { + int n=A.size(); + vectordp(A.size()+1,false); + dp[n]=true; + mapm; + for(int i=0;i=0;i--) + { + string temp; + for(int j=i;jarr[]){ + queueq; + q.push(src); + vectorvisited(V,false); + visited[src] = true; + while(!q.empty()){ + int u=q.front(); + q.pop(); + for(auto &x:arr[u]){ + int v = x.first; + if(!visited[v]){ + q.push(v); + } + } + } +} +for(int i = 0; i < V; i++){ + if(!visited[i]){ + BFS(i,arr); + } +} diff --git a/Graphs/BellmanFord.cpp b/Graphs/BellmanFord.cpp new file mode 100644 index 0000000..5688e9d --- /dev/null +++ b/Graphs/BellmanFord.cpp @@ -0,0 +1,24 @@ +// To find path from src to other vertices having min. sum of weights. +// Used for negative weights. +vector BellmanFord(int V,int src,vector>edges){ // {src,dest,weight} + vector dist(V,INT_MAX); // initialize to INT_MAX + dist[src]=0; //dist from src will be zero + for (int i = 1; i < V; i++) { + for (int j = 0; j < E; j++) { + int u = edges[j][0]; + int v = edges[j][1]; + int weight = edges[j][2]; + if (dist[u] != INT_MAX && dist[u] + weight < dist[v]) + dist[v] = dist[u] + weight; + } + } + for(int i=0; i < E; i++){ + int u=edges[i][0]; + int v=edges[i][1]; + int w=edges[i][2]; + if(dist[u] != INT_MAX && dist[u] + w q; + vectorcolor(V,-1); + for(int i = 0; i < V; i++){ + if(color[i] == -1){ + color[i] = 0; + q.push(i); + while(!q.empty()){ + int u = q.front(); + q.pop(); + for(auto &x:arr[u]){ + if(color[x] == -1){ + color[x] = 1-color[u]; + q.push(x); + } + else if (color[x] == color[u]) + return false; + } + } + } + } + return true; +} diff --git a/Graphs/Bridges.cpp b/Graphs/Bridges.cpp new file mode 100644 index 0000000..cd9ab73 --- /dev/null +++ b/Graphs/Bridges.cpp @@ -0,0 +1,23 @@ +// Find edges which when removed disconnects the graph +// ans contains the edges +// low -> lowest point reached using dfs from that point +// disc -> time of discovery of that point +void Bridges(){ + time++; + low[u] = time; + disc[u] = time; + for(auto &v:arr[u]){ + if(!visited[v]){ + parent[v] = u; + Bridges() + low[u] = min(low[u], low[v]); + if(low[v] > disc[u]){ + ans.push_back({u,v}); + } + } + else if (v != parent[u] ){ + low[u] = min(low[u], disc[v]); + } + } + return ans; +} diff --git a/Graphs/CutVertices.cpp b/Graphs/CutVertices.cpp new file mode 100644 index 0000000..4340e6e --- /dev/null +++ b/Graphs/CutVertices.cpp @@ -0,0 +1,81 @@ +void Graph::APUtil(int u, bool visited[], int disc[], + int low[], int parent[], bool ap[]) +{ + + static int time = 0; + + // Count of children in DFS Tree + int children = 0; + + // Mark the current node as visited + visited[u] = true; + + // Initialize discovery time and low value + disc[u] = low[u] = ++time; + + // Go through all vertices aadjacent to this + list::iterator i; + for (i = adj[u].begin(); i != adj[u].end(); ++i) + { + int v = *i; // v is current adjacent of u + + // If v is not visited yet, then make it a child of u + // in DFS tree and recur for it + if (!visited[v]) + { + children++; + parent[v] = u; + APUtil(v, visited, disc, low, parent, ap); + + // Check if the subtree rooted with v has a connection to + // one of the ancestors of u + low[u] = min(low[u], low[v]); + + // u is an articulation point in following cases + + // (1) u is root of DFS tree and has two or more chilren. + if (parent[u] == NIL && children > 1) + ap[u] = true; + + // (2) If u is not root and low value of one of its child is more + // than discovery value of u. + if (parent[u] != NIL && low[v] >= disc[u]) + ap[u] = true; + } + + // Update low value of u for parent function calls. + else if (v != parent[u]) + low[u] = min(low[u], disc[v]); + } +} + +// The function to do DFS traversal. It uses recursive function APUtil() +void Graph::AP() +{ + // Mark all the vertices as not visited + bool *visited = new bool[V]; + int *disc = new int[V]; + int *low = new int[V]; + int *parent = new int[V]; + bool *ap = new bool[V]; // To store articulation points + + // Initialize parent and visited, and ap(articulation point) arrays + for (int i = 0; i < V; i++) + { + parent[i] = NIL; + visited[i] = false; + ap[i] = false; + } + + // Call the recursive helper function to find articulation points + // in DFS tree rooted with vertex 'i' + for (int i = 0; i < V; i++) + if (visited[i] == false) + APUtil(i, visited, disc, low, parent, ap); + + // Now ap[] contains articulation points, print them + for (int i = 0; i < V; i++) + if (ap[i] == true) + cout << i << " "; +} + diff --git a/Graphs/CycleDetection_DirectedGraph.cpp b/Graphs/CycleDetection_DirectedGraph.cpp new file mode 100644 index 0000000..e48a185 --- /dev/null +++ b/Graphs/CycleDetection_DirectedGraph.cpp @@ -0,0 +1,15 @@ +void Cycle(int u,vector&visited,vectorarr[],vector&visited){ + if(!visited[u]){ + recstack[u] = true; + visited[u] = true; + for(auto &x:arr[u]){ + if(!visited[x] && Cycle(x,visited,arr,recstack)){ + return true; + } + else if(recstack[x]) + return true; + } + } + recstack[u] = false; + return false; +} diff --git a/Graphs/CycleDetection_UndirectedGraph.cpp b/Graphs/CycleDetection_UndirectedGraph.cpp new file mode 100644 index 0000000..33cbb68 --- /dev/null +++ b/Graphs/CycleDetection_UndirectedGraph.cpp @@ -0,0 +1,14 @@ +void Cycle(int u,vectorarr[],vectorvisited,int p){ + visited[u] = true; + + for(auto &x:arr[u]){ + + if(!visited[x] && Cycle(x,arr,visited,u)) + return true; + + else if(x != p) // to check for back edge. + return true; + } +} + +// call - Cycle(0, arr, visited, -1); diff --git a/Graphs/DFS.cpp b/Graphs/DFS.cpp new file mode 100644 index 0000000..83d6f75 --- /dev/null +++ b/Graphs/DFS.cpp @@ -0,0 +1,19 @@ +// dfs algorithm +// arr[u] is of the form {v, weight} +// V -> vertices +void dfs(int u,vector&visited, vectorarr[]){ + visited[u] = true; + for(auto &x:arr[u]){ + if(!visited[x.first]){ + dfs(x.first,visited,arr); + } + } +} + +int main(){ + // to cover entire graph in case it is disconnected. + for(int i=0;i, vector > , greater> > pq; + + // Create a vector for distances and initialize all + // distances as infinite (INF) + vector dist(V, INF); + + // Insert source itself in priority queue and initialize + // its distance as 0. + pq.push(make_pair(0, src)); + dist[src] = 0; + + /* Looping till priority queue becomes empty (or all + distances are not finalized) */ + while (!pq.empty()) + { + // The first vertex in pair is the minimum distance + // vertex, extract it from priority queue. + // vertex label is stored in second of pair (it + // has to be done this way to keep the vertices + // sorted distance (distance must be first item + // in pair) + int u = pq.top().second; + pq.pop(); + + // 'i' is used to get all adjacent vertices of a vertex + for (auto &i:arr[u]) + { + // Get vertex label and weight of current adjacent + // of u. + int v = i.first; + int weight = i.second; + + // If there is shorted path to v through u. + if (dist[v] > dist[u] + weight) + { + // Updating distance of v + dist[v] = dist[u] + weight; + pq.push(make_pair(dist[v], v)); + } + } + } + + // Print shortest distances stored in dist[] + printf("Vertex Distance from Source\n"); + for (int i = 0; i < V; ++i) + printf("%d \t\t %d\n", i, dist[i]); +} + diff --git a/Graphs/DisjointSetUnion.cpp b/Graphs/DisjointSetUnion.cpp new file mode 100644 index 0000000..d1d15fc --- /dev/null +++ b/Graphs/DisjointSetUnion.cpp @@ -0,0 +1,82 @@ +// Method 1 +// simply attach the subset of px to py. +int find(vector&parent, int x){ + if(parent[x] == -1){ + return x; + } + return parent[x] = find(parent,parent[x]); +} +void Union(int x, int y){ + int px = find(parent,x); + int py = find(parent,y); + parent[px] = py; +} +// If you want to check for cycle +int checkcycle(){ + for(int i = 0; i&parent,int x){ + if(parent[x] == -1){ + return x; + } + return parent[x] = find(parent,parent[x]); +} +int Union(){ + if(size[x] < size[y]){ + parent[x] = y; + } + else if(size[x] > size[y]){ + parent[y] = x; + } + else{ + parent[y] = x; + size[x] += size[y]; + } +} +void formDSU(){ + for(int i = 0;i < edges.size();i++){ + int x = edges[i][0]; + int y = edges[i][1]; + if(find(parent,x) != find(parent,y)) + Union(x,y); + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Graphs/FloydWarshall.cpp b/Graphs/FloydWarshall.cpp new file mode 100644 index 0000000..0e94642 --- /dev/null +++ b/Graphs/FloydWarshall.cpp @@ -0,0 +1,18 @@ +// to find the min. distances between all vertices of a graph +void FloydWarshall(vector>graph, int V){ + vectordp(V,vector(V,0)); + for(int i=0;i < V; i++){ + for(int j=0;j < V; j++){ + dp[i][j]=graph[i][j] + } + } + for(int k=0; k < V; k++){ + for(int i=0; i < V; i++){ + for(int j=0; j < V; j++){ + if(dp[i][k] != INT_MAX && dp[k][j] != INT_MAX && dp[i][k] + dp[k][j] < dp[i][j]){ + dp[i][j] = dp[i][k] + dp[k][j]; + } + } + } + } +} diff --git a/Graphs/LongestPathBtwAnyPairOfVert.cpp b/Graphs/LongestPathBtwAnyPairOfVert.cpp new file mode 100644 index 0000000..fa0104b --- /dev/null +++ b/Graphs/LongestPathBtwAnyPairOfVert.cpp @@ -0,0 +1,35 @@ +//change weight to -w for shortest path +//Method 1 - simple DFS O(V*(V+E)) +void LongestPath(int u, int sum, vector&visited, vectorarr[], int &ans){ + visited[src] = true; + int curr = 0; + for(auto &x:arr[u]){ + int v = x.first; + int w = x.second; + if(!visited[v]){ + curr = sum + w; + LongestPath(v, curr, visited, arr, ans); + } + ans=max(ans, curr); + } +} + +// Method 2- For a directed graph only O(V*(V+E)) +// Gives longest path between src and any other vertex +void LongestPath(int src){ + // create topological sort/ + vectordist(V,INT_MIN); + dist[src] = 0; + stacks; // s is the stack after topological sort + while(!s.empty()){ + int u = s.top(); + s.pop(); + for(auto &x:arr[u]){ + int v = x.first; + int w = x.second; + if(dist[v] < dist[u] + w){ + dist[v] = dist[u] + w; + } + } + } +} diff --git a/Graphs/MotherVertex.cpp b/Graphs/MotherVertex.cpp new file mode 100644 index 0000000..3baac92 --- /dev/null +++ b/Graphs/MotherVertex.cpp @@ -0,0 +1,25 @@ +// vertex from which we can access all other vertices. +void MotherVertex(){ + int v; + vectorarr[V]; // the graph + vectorvisited(V,false); + for(int i = 0; i < V; i++){ + dfs(i,visited,arr); + v = i; // candidate vertex + } + vectorvisited1(V,false); + dfs(v,visited1,arr); // dfs on candidate vertex + for(int i = 0; i < V;i++){ + if(!visited[i]) return -1; // check if there is any unvisited vertex. + } + return v; +} + +void dfs(int u, vector&visited,vectorarr[]){ + visited[u] = true; + for(auto &x : arr[u]){ + if(!visited[x]){ + dfs(x,visited,arr); + } + } +} diff --git a/Graphs/Prims.cpp b/Graphs/Prims.cpp new file mode 100644 index 0000000..f30224a --- /dev/null +++ b/Graphs/Prims.cpp @@ -0,0 +1,29 @@ +// to find the MST of the graph. +void Prims(int V,vectorarr[]){ // arr[u] is {v,weight} + vectorinMST(V,false); + vectorkey(V,INT_MAX); + vectorparent(V,-1); + int src=0; + priority_queue< pair, vector> , greater> > pq; + pq.push({0,src}); + key[src]=0; + while(!pq.empty()){ + auto p = pq.top(); + pq.pop(); + int u = p.second; + inMST[u] = true; + for(auto &x:arr[u]){ + int v = x.first; + int w = x.second + if(!inMST[v] && key[v] > w){ + key[v] = w; + pq.push({key[v],v}); + parent[v] = u; + } + } + } + for(int i=1; i < V; i++){ + cout<< parent[i] << " " << i <<"\n"; + } + // key[] contains the weight attached with each vertex. to get the sum of weights of MST, just add all elements in key +} diff --git a/Graphs/README.md b/Graphs/README.md new file mode 100644 index 0000000..9e48c58 --- /dev/null +++ b/Graphs/README.md @@ -0,0 +1,2 @@ +

Popular graph algorithms and problems (in cpp)

+Algos on flow not included for now diff --git a/Graphs/TopologicalSort.cpp b/Graphs/TopologicalSort.cpp new file mode 100644 index 0000000..66365f3 --- /dev/null +++ b/Graphs/TopologicalSort.cpp @@ -0,0 +1,16 @@ +// This yields the topological sort for the DAG arr[] +// vertex with indegree 0, 1, 2, and so on... +/* *****Applications****** + 1. Sorted dictionary of alien language. (popular question) + 2. Longest path problems for DAG. + 3. Add max edges so that no cycle is formed. +*/ +void Topo(stack&s,vector&visited,vectorarr[],int u){ + visited[u] = true; + for(auto &x:arr[u]){ + if(!visited[x]){ + Topo(s,visited,arr,x); + } + } + s.push(u); +}