├── Advanced Topics ├── Binary Index Tree │ └── Resources.md ├── Convex Hull Trick │ └── dp_cht.pdf └── Segment Tree │ └── Resources.md ├── CONTRIBUTING.md ├── Dynamic Programming ├── Easy │ ├── 0-1 Knapsack │ │ ├── LinkToProblem.md │ │ ├── Solution.md │ │ └── source.cpp │ ├── Count Number Of Hops │ │ ├── LinkToProblem.md │ │ ├── Solution.md │ │ └── source.cpp │ ├── Dice Combinations │ │ ├── LinkToProblem.md │ │ ├── Solution.md │ │ └── source.cpp │ ├── Longest Increasing Subsequence │ │ ├── LinkToProblem.md │ │ ├── Solution.md │ │ └── source.cpp │ └── Subset Sum │ │ ├── LinkToProblem.md │ │ ├── Solution.md │ │ └── source.cpp ├── Medium │ ├── Aibohphobia - SPOJ │ │ ├── LinkToProblem.md │ │ ├── Solution.md │ │ └── source.cpp │ ├── Edit Distance │ │ ├── LinkToProblem.md │ │ ├── Solution.md │ │ └── source.cpp │ ├── Egg Dropping Puzzle │ │ ├── LinkToProblem.md │ │ ├── Solution.md │ │ └── source.cpp │ ├── Longest Common Subsequence │ │ ├── LinkToProblem.md │ │ ├── Solution.md │ │ └── source.cpp │ └── The Painter's Partition Problem │ │ ├── LinkToProblem.md │ │ ├── Solution.md │ │ └── source.cpp └── Resources.md ├── Graphs └── Maximum Flow │ └── Resources.md ├── LICENSE ├── README.md ├── SolutionTemplate.md └── turing.jpg /Advanced Topics/Binary Index Tree/Resources.md: -------------------------------------------------------------------------------- 1 | ### Resources for Binary Index Tree 2 | 3 | Binary Index Tree is a bit tricky topic and for such topics it is always beneficial to read from more than one resource. 4 | 5 | Here is a list to get started:- 6 | * Topcoder: [Basic idea on Binary Index Tree](https://www.topcoder.com/community/competitive-programming/tutorials/binary-indexed-trees/) 7 | * Codeforces: [A blog on Binary Index Trees](https://codeforces.com/blog/entry/619) 8 | * Geeks for Geeks: [Binary Index Tree or Fenwick Tree](https://www.geeksforgeeks.org/binary-indexed-tree-or-fenwick-tree-2/) 9 | * Kartik Kukreja's Wordpress Blog: [Range Updates with Fenwick Tress](https://kartikkukreja.wordpress.com/2013/12/02/range-updates-with-bit-fenwick-tree/) 10 | * cp-algorithms: [Fenwick Tree](https://cp-algorithms.com/data_structures/fenwick.html) 11 | 12 | In the cp-algorithms website whose link is provided above, there are a lot of practice problems on Binary index Trees from various websites. -------------------------------------------------------------------------------- /Advanced Topics/Convex Hull Trick/dp_cht.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/algoholics-ntua/algorithms/2306db43192c598cb8ec431cc6c6e564699619f0/Advanced Topics/Convex Hull Trick/dp_cht.pdf -------------------------------------------------------------------------------- /Advanced Topics/Segment Tree/Resources.md: -------------------------------------------------------------------------------- 1 | ### Resources for Segment tree 2 | 3 | We suggest to read from more than one source, in order to build a good intuition on the topic: 4 | 5 | * Hackerearth: [Introduction to Segment Tree](https://www.hackerearth.com/practice/data-structures/advanced-data-structures/segment-trees/tutorial/) 6 | * TopCoder: [Range Minimum Query and Lowest Common Ancestor](https://www.topcoder.com/community/competitive-programming/tutorials/range-minimum-query-and-lowest-common-ancestor/) 7 | * Blog: [A simple approach to segment trees](https://kartikkukreja.wordpress.com/2014/11/09/a-simple-approach-to-segment-trees/) 8 | * VisualAlgo: [Visualization of Min Segment Tree](https://visualgo.net/en/segmenttree) 9 | * Hackerearth: [Introduction to lazy propagation in Segment Tree](https://www.hackerearth.com/practice/notes/segment-tree-and-lazy-propagation/) 10 | 11 | Here is a [first question](https://www.hackerearth.com/practice/data-structures/advanced-data-structures/segment-trees/practice-problems/algorithm/range-minimum-query/) to practice. 12 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contribution Guidelines 2 | 3 | Thank you for your interest in contributing to our repository! 4 | 5 | ### How can I contribute? 6 | 7 | * Open issues for any bug or logical error found in a problem's solution 8 | * Propose different solutions to existing problems or add new ones 9 | * Add resources that you find helpful for understanding a topic 10 | 11 | ### Code of Conduct 12 | 13 | All contributions to the repository are made through [pull requests.](https://help.github.com/articles/about-pull-requests/) 14 | 15 | To keep our repository organized, you should follow the file structure found in [README.](README.md) 16 | Also, a problem's folder should contain the solution in a programming language of your choice (C++, Python, Haskell, JS etc.) , a [markdown file](https://guides.github.com/features/mastering-markdown/) briefly explaining your approach and a file with link to the problem: 17 | 18 | ``` 19 | ├── SomeRandomProblem 20 | ├── LinkToProblem.md 21 | ├── Solution.md 22 | └── source.py 23 | ``` 24 | Make sure your code is readable and can easily be followed by anyone interested in your solution. 25 | For not wasting too much time on _Solution.md_, you can download and modify the [template.](SolutionTemplate.md) 26 | Please note that you should also include the problem on the corresponding topic's problem list held in _Resources.md_. 27 | 28 | Have fun coding! 29 | -------------------------------------------------------------------------------- /Dynamic Programming/Easy/0-1 Knapsack/LinkToProblem.md: -------------------------------------------------------------------------------- 1 | [0-1 Knapsack](https://practice.geeksforgeeks.org/problems/0-1-knapsack-problem/0) 2 | -------------------------------------------------------------------------------- /Dynamic Programming/Easy/0-1 Knapsack/Solution.md: -------------------------------------------------------------------------------- 1 | ### Problem: [0-1 Knapsack](https://practice.geeksforgeeks.org/problems/0-1-knapsack-problem/0) 2 | ### Topic: Dynamic Programming 3 | 4 | __Problem Statement:__ Given N items with certain values and weights, and a knapsack with capacity W, calculate the maximum total value we can put in our knapsack. Note that we can either take an item or not, we can not take a portion of it. 5 | 6 | Let's define the subproblem T(n,w) = {maximum value we can fit in a knapsack of capacity w, using items [0..n]}. The answer to our problem will be T(N-1,W). 7 | 8 | We will try to calculate T(n,w) recursively. There are 2 options for the n-th item, we can either put it in the knapsack or not. 9 | 10 | If we put it in the knapsack, we now have W-weight[n] remaining capacity to fill with [0..(n-1)] items, but we have increased the value of the knapsack by value[n]. 11 | 12 | If we don't take the n-th item, then we just have W capacity to fill with [0..(n-1)] items. 13 | 14 | Of course, if the weight of an item is bigger than the remaining capacity then we can not take it and we fall to case 2. 15 | 16 | ``` 17 | T(n,w) = max( T(n-1,w) , value[n] + T(n-1,w-weight[n]) ) 18 | ``` 19 | 20 | Our base case is for n==0: 21 | 22 | ``` 23 | if(w 2 | 3 | #define MAX_N 100 4 | #define MAX_W 100 5 | 6 | using namespace std; 7 | 8 | int N,T,W; 9 | int weight[MAX_N],value[MAX_N]; 10 | int memo[MAX_N][MAX_W+1]; 11 | 12 | int max(int x, int y){ return (x>y) ? x:y; } 13 | 14 | void initialize(){ 15 | for(int i=0;i=weight[0]) ? value[0]:0; 26 | 27 | int result; 28 | 29 | if(w 2 | #include 3 | 4 | #define MAX_N 50 5 | 6 | using namespace std; 7 | 8 | int T,N; 9 | int a[MAX_N+1]; 10 | 11 | int hops(int n){ 12 | 13 | if(n<0) return 0; 14 | 15 | if(n==0) return 1; 16 | 17 | if(a[n]!=0) return a[n]; 18 | 19 | int result = hops(n-1) + hops(n-2) + hops(n-3); 20 | 21 | a[n] = result; 22 | 23 | return result; 24 | } 25 | 26 | int main(){ 27 | scanf("%d",&T); 28 | 29 | memset(a,0,sizeof(a[0])*(MAX_N+1)); //initialization 30 | 31 | while(T--){ 32 | scanf("%d",&N); 33 | //no need for initialization of the a array 34 | //some answers will have been computed in previous testcases 35 | //and we are solving the same problem with different size 36 | printf("%d\n",hops(N)); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Dynamic Programming/Easy/Dice Combinations/LinkToProblem.md: -------------------------------------------------------------------------------- 1 | [Dice Combinations](https://cses.fi/problemset/task/1633) 2 | -------------------------------------------------------------------------------- /Dynamic Programming/Easy/Dice Combinations/Solution.md: -------------------------------------------------------------------------------- 1 | ### Problem: [Dice Combinations](https://cses.fi/problemset/task/1633) 2 | ### Topic: Dynamic Programming 3 | 4 | 5 | __Problem Statement:__ Your task is to count the number of ways to construct sum n by throwing a dice one or more times. Each throw produces an outcome between 1 and 6. 6 | 7 | To arrive at the step N, our previous one was N-1, N-2 or N-3....N-6, because we can only only get 1, 2 ... 6 from the dice. 8 | So, the number of ways we can get to N, is equal to the sum of ways we can go to N-1, N-2 to N-6 . 9 | 10 | ``` 11 | T(n): 12 | if(n==0||n==1) return 1; 13 | if(n<0) return 0; 14 | 15 | return T(n-1) + T(n-2) + T(n-3) + T(n-4) + T(n-5) + T(n-6) 16 | ``` 17 | 18 | The above solution without memoization has a time complexity of O(n^6) but reduces to Θ(n) when memoized!!! 19 | So it can be compiled before 1 sec. 20 | -------------------------------------------------------------------------------- /Dynamic Programming/Easy/Dice Combinations/source.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | using namespace std; 4 | #define ll long long int 5 | const ll mod=1e9+7; 6 | int vec[1000001]; 7 | 8 | int main() 9 | { 10 | vec[0]=1; 11 | vec[1]=1; 12 | ll n; 13 | cin>>n; 14 | 15 | for(int i=2;i<=n+1;i++){ 16 | for(int j=1;j<=6;j++) 17 | vec[i]+= ((i-j)>=0)? vec[i-j]: 0; 18 | vec[i]%=mod; 19 | } 20 | 21 | cout< [0..N-1]. 7 | 8 | The LIS ending at index i, can either be just a[i], or a sequence that its previous value is any number in a[0..i-1] which is less than a[i]. 9 | 10 | In the first case the answer is LIS(i) = 1. 11 | In the second case, if the previous value is a[k], then the answer will be 1 plus the LIS ending at index k : 1 + LIS(k). To obtain the answer, we must find the maximum for all possible values of k: 12 | 13 | ``` 14 | LIS(i): 15 | result = 1 16 | for(int k=0; k 2 | #include 3 | #include 4 | 5 | #define MAX_N 1000 6 | 7 | using namespace std; 8 | 9 | int N,T; 10 | int a[MAX_N],memo[MAX_N]; 11 | 12 | int LIS(int k){ 13 | // Longest Increasing Subsequence that ends at index k 14 | if(memo[k]!=0) return memo[k]; 15 | 16 | int result = 1; 17 | 18 | for(int i=0;i>T; 38 | 39 | while(T--){ 40 | cin>>N; 41 | 42 | for(int i=0;i>a[i]; 43 | 44 | if(N==0){ 45 | cout<<"0\n"; //geeksforgeeks have test cases with N=0... 46 | continue; 47 | } 48 | 49 | initialize(N); 50 | 51 | int result = 1; 52 | 53 | for(int i=0;i 2 | 3 | #define MAX_N 100 4 | #define MAX_Ai 1000 5 | 6 | using namespace std; 7 | 8 | int T,N,a[MAX_N]; 9 | int sum; 10 | int memo[MAX_N][MAX_N*MAX_Ai]; 11 | // -1 => not calculated, 0 => false, 1 => true 12 | 13 | bool dp(int n, int s){ 14 | 15 | if(memo[n][s]!=-1) return (memo[n][s]==1); 16 | 17 | if(n==0) return (s==0 || s==a[0]); 18 | 19 | bool result = dp(n-1,s-a[n]) || dp(n-1,s); 20 | 21 | memo[n][s] = (result) ? 1:0; 22 | 23 | return result; 24 | 25 | } 26 | 27 | void initialize(int n, int s){ 28 | for(int i=0;i 2 | #include 3 | 4 | #define MAX_S 6100 5 | 6 | using namespace std; 7 | 8 | int T; 9 | string s; 10 | int memo[MAX_S][MAX_S]; //memo table for the dp function makePalindrome 11 | void initialize(){ 12 | int length=s.length(); 13 | for(int i=0;i>T; 34 | while(T--){ 35 | cin>>s; 36 | initialize(); 37 | printf("%d\n",makePalindrome(0,s.length()-1)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Dynamic Programming/Medium/Edit Distance/LinkToProblem.md: -------------------------------------------------------------------------------- 1 | [Edit Distance](https://practice.geeksforgeeks.org/problems/edit-distance/0) 2 | -------------------------------------------------------------------------------- /Dynamic Programming/Medium/Edit Distance/Solution.md: -------------------------------------------------------------------------------- 1 | ### Problem: [Edit Distance](https://practice.geeksforgeeks.org/problems/edit-distance/0) 2 | ### Topic: Dynamic Programming 3 | 4 | Problem statement : Given two strings (s1, s2) calculate the minimum number of operations (insert, remove, replace) required to convert s1 into s2. 5 | 6 | This is a classical DP problem with optimal substructure property. We will use the prefixes of the strings to define the subproblem T(n,m) = { min cost to convert s1[0..n] to s2[0..m] }. Obviously, the answer we are looking for is T(|s1|-1, |s2|-1). 7 | 8 | We will compute T(n,m) by using smaller subproblems while performing all the possible operations. 9 | Start by looking at the end of the strings: 10 | 11 | * If the last characters are the same, we just have to make the rest of the strings identical: 12 | 13 | ``` 14 | if( s1[n] == s2[m] ) then T(n,m) = T(n-1,m-1) 15 | ``` 16 | 17 | * If the last characters are not the same, then we have to make an operation to fix them and then recursively make the rest of the strings identical: 18 | 19 | For example, let s1 = 'ABCC' and s2 = 'ABCDE'. The last characters are not the same ( 'C' != 'E' ). 20 | 21 | Possible moves to fix the last chars: 22 | 23 | 1) Insert 'E' at the end of s1 which is the same as the last char of s2 and we recursively solve for s1 = 'ABCC' and s2 = 'ABCD' 24 | In the general case that will cost: T(n,m) = 1 + T(n,m-1) 25 | 26 | 2) Replace the letter 'C' at the end of s1 with an 'E' and solve recursively for s1 = 'ABC' and s2 = 'ABCD' 27 | In the general case that will cost: T(n,m) = 1 + T(n-1,m-1) 28 | 29 | 3) Remove the last letter of s1 and try to recursively solve for s1 = 'ABC' and s2 = 'ABCD' 30 | In the general case that will cost: T(n,m) = 1 + T(n-1,m) 31 | 32 | So, 33 | 34 | ``` 35 | if( s1[n] != s2[m] ) then T(n,m) = 1 + min( T(n-1,m), T(n-1,m-1), T(n,m-1) ) 36 | ``` 37 | 38 | Base case: 39 | 40 | If either of the strings are empty, the conversion cost will be the length of the other string. 41 | -------------------------------------------------------------------------------- /Dynamic Programming/Medium/Edit Distance/source.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAX_LENGTH 100 5 | 6 | using namespace std; 7 | 8 | string s1,s2; 9 | int memo[MAX_LENGTH][MAX_LENGTH]; 10 | int T,length1,length2; 11 | 12 | int min(int x, int y, int z){ return min(x,min(y,z)); } 13 | 14 | void initialize(int l1, int l2){ 15 | 16 | for(int i=0;i>T; 60 | 61 | while(T--){ 62 | cin>>length1>>length2>>s1>>s2; 63 | 64 | initialize(length1,length2); 65 | 66 | cout<[1..n] : min{ max{ T(n-i,k), T(i-1,k-1) } } 30 | ``` 31 | 32 | Base cases: 33 | 34 | ``` 35 | T(n,1) = n 36 | T(1,k) = 1 37 | ``` 38 | -------------------------------------------------------------------------------- /Dynamic Programming/Medium/Egg Dropping Puzzle/source.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAX_K 10 5 | #define MAX_N 100 6 | 7 | using namespace std; 8 | 9 | int DP[MAX_N+1][MAX_K+1]; 10 | int N,K,T; 11 | 12 | inline int max(int a,int b){ return (a>b) ? a:b;} 13 | inline int min(int a,int b){ return (a 2 | #include 3 | 4 | #define MAX_LENGTH 100 5 | 6 | using namespace std; 7 | 8 | string s1,s2; 9 | int l1,l2; 10 | int memo[MAX_LENGTH][MAX_LENGTH]; //memo table for dp 11 | 12 | void initialize(){ 13 | for(int i=0;i>T; 37 | 38 | while(T--){ 39 | cin>>l1>>l2; 40 | cin>>s1>>s2; 41 | 42 | initialize(); 43 | 44 | cout< 2 | #include 3 | #include 4 | 5 | #define MAX_N 50 6 | #define MAX_K 30 7 | 8 | using namespace std; 9 | 10 | int T,N,K,length[MAX_N],partialSum[MAX_N]; // partialSum[i] = length[0]+...length[i] 11 | int memo[MAX_N][MAX_K+1]; 12 | 13 | 14 | int dp(int n, int k){ 15 | // min time to paint first 0..n boards, using k painters 16 | 17 | if( memo[n][k]!=-1 ) return memo[n][k]; 18 | 19 | int result = INT_MAX; 20 | 21 | for(int b=1;b<=n;b++){ // iterating on all possible number of boards the k-th painter can paint 22 | result = min( result , max(dp(n-b,k-1),partialSum[n]-partialSum[n-b]) ); 23 | } 24 | 25 | memo[n][k]=result; 26 | 27 | return result; 28 | } 29 | 30 | 31 | void initialize(int n, int k){ 32 | for(int i=0;i