├── .gitignore ├── Adhoc + Basic ├── Reservoir_sampling.cpp ├── Sieve_of_Eratosthenes.cpp ├── Two_Pointer.cpp ├── binary_search_I.cpp ├── binary_search_II.cpp └── binary_search_III.cpp ├── Arrays ├── MedianOfSortedArrays.cpp ├── MedianOfStream.cpp ├── MonotonicStack.cpp ├── Sliding Window Max.cpp ├── TrappingRainwater.cpp └── readme.md ├── Bit-mask └── Bitmask_Basic.cpp ├── DP ├── LCS.cpp ├── LIS.cpp ├── LongestPalindromicSubstring.cpp ├── LongestPanlidromicSubsequence.cpp ├── MatrixChainMulti.cpp ├── PalindromicCuts.cpp ├── digit_dp.cpp └── travelling_salesman_prob.cpp ├── Geometry └── anglecoverted.cpp ├── Graph ├── BFS.cpp ├── Bellman_ford(Negative_weights).cpp ├── Bipartite_Coloring.cpp ├── Bipartite_matching.cpp ├── DFS.cpp ├── FloydWarshall.cpp ├── README.md ├── cycleDetection.cpp ├── dijkstra.cpp ├── prims_algo.cpp ├── topological_sort.cpp └── union_find_algo.cpp ├── Greedy or DP (Problems) ├── Continuous_subarray_sum.cpp ├── Job_scheduling.cpp ├── Kadane.cpp ├── Queue_Reconstruction.cpp ├── jump_problem.cpp └── variations.txt ├── Matrix or Backtracking(Problems) └── Max_Submatrix_with_LT_Ksum.cpp ├── NumberTheory └── RandomNum.cpp ├── OS Concept based algos └── LRU-Cache.cpp ├── Quick Revise Documents ├── Recursion_BackTracking.pdf ├── System-Design-educative.io.pdf ├── Trees_Part_1.pdf └── Trees_Part_2.pdf ├── README.md ├── Range_queries ├── Mo's_algo.cpp ├── Persisitant tree.cpp ├── Range_Update(Difference_Array).cpp ├── Segment_trees.cpp ├── sparce_table.cpp ├── sqrt_decomposition.cpp └── which_to_use_when.txt ├── Sorting Algorithms ├── HeapSort.cpp ├── Inbuilt_sorting_algos.cpp ├── MergeSort.cpp ├── O(n^2)_Algos.cpp ├── QuickSort.cpp ├── RadixSort.cpp └── cycleSort.cpp ├── Strings ├── KMP.cpp ├── PatternMatching.cpp └── string_input.cpp ├── Trees ├── Binary_Lifting.cpp ├── LCA.cpp ├── WordSearch2.cpp └── trie.cpp └── codesnippet.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/* -------------------------------------------------------------------------------- /Adhoc + Basic/Reservoir_sampling.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Question: Is there a way to get random number from a stream of integers? 3 | * Yes. We create a reserviour of size 1 (single element). 4 | * We iterate over the stream and for each element we have a probability of 1/i to replace the element in the reserviour. 5 | * This is because the probability of not replacing the element is (i-1)/i and the probability of replacing the element is 1/i. 6 | * So the probability of not replacing the element after i iterations is (i-1)/i * (i-2)/i-1 * ... * 1/2 = 1/i. 7 | * 8 | * Ref: https://www.youtube.com/watch?v=A1iwzSew5QY 9 | * Que: https://leetcode.com/problems/linked-list-random-node/ 10 | */ 11 | 12 | #include 13 | 14 | using namespace std; 15 | 16 | int findRandom(vector arr) 17 | { 18 | int reservoir, len = 0; 19 | 20 | reservoir = arr[0]; 21 | len = 1; 22 | 23 | while (len < arr.size()) 24 | { 25 | // probability of replacing charachter in reservoir is 1/len 26 | // Assuming rand() produces int upto infinity 27 | if (rand() % len == 0) 28 | { 29 | reservoir = arr[len]; 30 | } 31 | len++; 32 | } 33 | 34 | return reservoir; 35 | } 36 | 37 | // getting random index based on weight in a stream on weights 38 | // print randomNum when 0 comes in stream 39 | int weightedRandomIndex(const std::vector& weights) { 40 | double totalWeight = 0; 41 | int selectedIndex = -1; 42 | 43 | for (int i = 0; i < weights.size(); ++i) { 44 | if (weights[i] == 0) cout << selectedIndex; 45 | 46 | totalWeight += weights[i]; 47 | if (((double)rand()) / RAND_MAX * totalWeight < weights[i]) { 48 | selectedIndex = i; 49 | } 50 | } 51 | return selectedIndex; 52 | } 53 | 54 | int main() 55 | { 56 | vector arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 57 | 58 | cout << "Radom num from inf list is " << findRandom(arr); 59 | } 60 | -------------------------------------------------------------------------------- /Adhoc + Basic/Sieve_of_Eratosthenes.cpp: -------------------------------------------------------------------------------- 1 | /*Questions solved 2 | precomputation -> O(N(lnlnN)) 3 | 1. is n a prime -> O(1) 4 | 2. factors of some F -> O(ln NF) 5 | 3. primes between a range -> O(range) 6 | 4. smallest prime greater than k -> O(ln k) 7 | */ 8 | 9 | #include 10 | 11 | using namespace std; 12 | #define LIM 10000 13 | 14 | bool isComposite[LIM]; 15 | int factor[LIM]; //stores one of the factor of the indx, we can find other factor easily 16 | vector primes; //stores list of primes in LIM 17 | 18 | int main() 19 | { 20 | int i; 21 | //PreComputation 22 | isComposite[1]=true; //assume for simplicity as 1 is NOT PRIME. 23 | for(int i=2;i>n; 44 | cout<>F; 50 | 51 | while (isComposite[F] and F!=1) 52 | { 53 | cout<>a>>b; 62 | auto itr = upper_bound(primes.begin(),primes.end(),a); 63 | for( ; *itr <= b and itr!=primes.end() ; itr++ ) 64 | { 65 | cout<<*itr<<" "; 66 | } 67 | 68 | //Q4 69 | int k; 70 | cin>>k; 71 | cout<<"Enter number to get just greater prime:"; 72 | cin>>k; 73 | itr = upper_bound(primes.begin(),primes.end(),k); 74 | if(itr!=primes.end()) 75 | cout<<*itr; 76 | 77 | 78 | 79 | } 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /Adhoc + Basic/Two_Pointer.cpp: -------------------------------------------------------------------------------- 1 | // Dutch National Flag Problem 2 | // Sot 0,1,2 with a single traversal 3 | 4 | /* 5 | * Must satisfy condn 6 | * [start,lo] = 0 7 | * [hi+1,end] = 2 8 | * [mid, hi-1] = Don't know 9 | */ 10 | // Array has 0,1,2 as elements sort the array: 11 | void sortColors(vector& arr) { 12 | int lo=0,mid=0,hi=arr.size()-1; 13 | // 14 | while(mid <= hi) { 15 | if(arr[mid] == 0) 16 | swap(arr[lo++],arr[mid]); 17 | else if(arr[mid] == 1) 18 | mid++; 19 | else // arr[mid] = 2 20 | swap(arr[hi--],arr[mid]); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Adhoc + Basic/binary_search_I.cpp: -------------------------------------------------------------------------------- 1 | // Question link -> https://community.topcoder.com/stat?c=problem_statement&pm=1901&rd=4650 2 | // Artical link -> https://www.topcoder.com/community/competitive-programming/tutorials/binary-search 3 | // Ref link -> https://www.youtube.com/watch?v=GU7DpgHINWQ 4 | // Ref link -> https://leetcode.com/discuss/interview-question/1322500/5-variations-of-Binary-search-(A-Self-Note)/?fbclid=IwAR1tgOv9b7dNA9dyqBEHCmNdqkGrBxItE7vqBRVqL0Rk6UE65_fLO8J1JI8 5 | 6 | // Here in binary search we basically want o function that return boolean value if it is ans yes or no 7 | // And we want the indxe from where true begins or false begins 8 | #include 9 | 10 | using namespace std; 11 | 12 | int getMostWork_method1(int folders[], int workers,int n) 13 | { 14 | // Number of workers maximum in a division can be between 1 and 10^6(Can be lower but in general) 15 | int lo = 1, hi = 1e5+1; 16 | 17 | while (lo < hi) 18 | { 19 | int mid = lo + (hi - lo) / 2; 20 | int required = 1, sum = 0; 21 | 22 | for (int i = 0; i < n; ++i) 23 | { 24 | if (sum + folders[i] <= mid) // the current worker can handle it 25 | sum += folders[i]; 26 | else // assign nemidt worker 27 | { 28 | ++required; 29 | sum = folders[i]; 30 | } 31 | } 32 | // | is the indx we want to find 33 | // F F F F F F F T T T T T T 34 | // if(p(mid)==true) hi = mid 35 | if (required <= workers) 36 | hi = mid; 37 | else 38 | lo = mid + 1; 39 | } 40 | return lo; // lo=hi so doesn't matter 41 | } 42 | 43 | bool ispossible(int folders[],int n, int no, int workers) 44 | { 45 | int required = 1, sum = 0; 46 | for (int i = 0; i < n; ++i) 47 | { 48 | if (sum + folders[i] <= no) // the current worker can handle it 49 | sum += folders[i]; 50 | else // assign nemidt worker 51 | { 52 | ++required; 53 | sum = folders[i]; 54 | } 55 | } 56 | if(required <= workers) 57 | return true; 58 | return false; 59 | } 60 | 61 | int getMostWork_method2(int folders[],int workers, int n) 62 | { 63 | int hi=1e9,lo=0,mid; 64 | bool check_low,check_mid,check_upp; 65 | 66 | while(lo <= hi) 67 | { 68 | mid = (lo+hi)/2; 69 | check_low=ispossible(folders,n,mid-1,workers); 70 | check_mid=ispossible(folders,n,mid,workers); 71 | check_upp=ispossible(folders,n,mid+1,workers); 72 | 73 | if(check_low==0 && check_mid==1) 74 | return mid; 75 | else if(check_mid==0 && check_upp==1) 76 | return mid+1; 77 | else if(check_upp==1) 78 | hi=mid+1; 79 | else if(check_low==0) 80 | lo=mid-1; 81 | } 82 | return 0; 83 | } 84 | 85 | int main() 86 | { 87 | int arr[15] = { 568, 712, 412, 231, 241, 393, 865, 287, 128, 457, 238, 98, 980, 23, 782 }; 88 | int n = sizeof(arr)/sizeof(int); 89 | 90 | // Divide the work in 4 workers such that the work done per worker is minimum 91 | cout << "Minimum possible maximum folders per person " < https://www.youtube.com/watch?v=U66U1-umNbQ&t=1s 2 | // Reference --> https://www.youtube.com/watch?v=V343UXw4P3Y 3 | 4 | // upper bound return first element which is >value. If not, return end(). 5 | // lower bound return first element which is ≥value. If not, return end(). 6 | 7 | /* 8 | Elements are : 1 3 5 7 9 9 | ******* lower_bound ********* 10 | lower bound of 5 in the set is: 5 11 | lower bound of 1 in the set is: 1 12 | lower bound of 4 in the set is: 5 13 | ****** upper_bound ************ 14 | upper bound of 5 in the set is: 7 15 | upper bound of 1 in the set is: 3 16 | upper bound of 4 in the set is: 5 17 | */ 18 | 19 | #include 20 | using namespace std; 21 | 22 | /* 23 | * Intresting observation note worthy : 24 | * lo+(hi-lo)/2 = (lo+hi)/2 is skewed to towards lo. (ex. (1+4)/2 = 2.5 but it return 2) 25 | * hi = mid can be seen a skewed towards hi so this (lo+hi)/2 works fine with hi = mid 26 | * Similarly 27 | * lo = mid is skewed towards lo so using (lo+hi)/2 A as mid will result in SEG so instead use 28 | * (hi-lo+1)/2 is skewed towards hi ex. 1+(4-1+1)/2 = 3.5 = 3 so we got ceil(2.5) 29 | * mid = lo + (hi-lo+1)/2 30 | */ 31 | 32 | int lower_bound_(vector arr, int target){ 33 | int lo = 0; 34 | int hi = arr.size()-1; 35 | 36 | while(lo target) 42 | hi = mid-1; 43 | // Our index needed may be this index mid or may be less than mid. 44 | else 45 | hi = mid; 46 | } 47 | return lo; 48 | } 49 | 50 | int upper_bound_(vector arr, int target){ 51 | int lo = 0; 52 | int hi = arr.size()-1; 53 | 54 | while(lo target) 60 | hi = mid-1; 61 | // Our index needed may be this index mid or may be greater than mid. 62 | else 63 | lo = mid; 64 | } 65 | return lo; 66 | } 67 | 68 | /* 69 | Rotated sorted array will look something like this 70 | only at pivot arr[pivot] > arr[pivot+1] 71 | / 72 | / 73 | / <- case 1 (mid > arr[0]) 74 | / 75 | / 76 | / <- case 2 (mid < arr[0]) 77 | / 78 | ex. {4, 5, 6, 7, 0, 1, 2} 79 | */ 80 | int find_pivot(vector &arr) { 81 | 82 | int lo = 0, hi = arr.size()-1; 83 | 84 | while(lo < hi) { 85 | int mid = (lo+hi)/2; 86 | if(arr[mid] > arr[0]){ 87 | if(arr[mid] > arr[mid+1]) 88 | return mid; 89 | else 90 | lo = mid+1; 91 | } 92 | else{ 93 | if(arr[mid-1] > arr[mid]) 94 | return mid-1; 95 | else 96 | hi = mid-1; 97 | } 98 | } 99 | return lo; 100 | } 101 | 102 | 103 | int pivotedBinarySearch(vector &arr, int target){ 104 | // Task 1: Find the highest elements index 105 | // Task 2: Simple binary search in one of the ranges 106 | 107 | int pivot = find_pivot(arr); 108 | 109 | vector :: iterator it; 110 | if(target >= arr[0]) 111 | it = lower_bound(arr.begin(),arr.begin()+pivot,target); 112 | else 113 | it = lower_bound(arr.begin()+pivot+1, arr.end(),target); 114 | 115 | if(*it != target) 116 | return -1; 117 | else 118 | return it-arr.begin(); 119 | } 120 | 121 | 122 | 123 | int main(){ 124 | // Array is sorted then rotated task is to find index of key element. 125 | vector arr = { 5, 6, 7, 8, 9, 10, 1, 2, 3 }; 126 | cout << "Index of the element is : "<< pivotedBinarySearch(arr, 2); 127 | 128 | 129 | } 130 | -------------------------------------------------------------------------------- /Adhoc + Basic/binary_search_III.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int lowerBound(vector arr, int target) { 6 | int left = 0; 7 | int right = arr.size() - 1; 8 | int result = -1; 9 | 10 | while (left <= right) { 11 | int mid = left + (right-left)/2; // To help with out of bounds 12 | if (arr[mid] >= target) { // we want the value in ans if the target exists 13 | result = mid; 14 | right = mid - 1; 15 | } 16 | else { 17 | left = mid + 1; 18 | } 19 | } 20 | return result; 21 | } 22 | 23 | int upperBound(vector arr, int target) { 24 | int left = 0; 25 | int right = arr.size() - 1; 26 | int result = -1; 27 | 28 | while (left <= right) { 29 | int mid = left + (right-left)/2; // To help with out of bounds 30 | if (arr[mid] > target) { // we want a greater than target value. 31 | result = mid - 1; 32 | right = mid - 1; 33 | } 34 | else { 35 | left = mid + 1; 36 | } 37 | } 38 | return result; 39 | } -------------------------------------------------------------------------------- /Arrays/MedianOfSortedArrays.cpp: -------------------------------------------------------------------------------- 1 | // Problem Link : https://leetcode.com/problems/median-of-two-sorted-arrays/ 2 | /* 3 | 4 | If we merge two arrays in sorted manner the central values will give us the median 5 | 6 | 1 4 5 7 | 2 6 7 8 9 8 | 9 | 1 2 4 5 6 7 8 9 -> (5+6)/2 10 | 11 | The left half and right half of this combined array has elements from both arrays 12 | 13 | 1 4 5 | INT_MAX <- from arr1 (INT_MAX because there was no other element to right, similarly INT_MIN if there's no element to left) 14 | 2 | 6 7 8 9 <- from arr2 15 | 16 | all elements in the left half should be smaller than all elements on right in this configuration 17 | so basically 5<6 && 2 32 | using namespace std; 33 | 34 | class Solution { 35 | public: 36 | double findMedian(vector&a,vector&b){ 37 | int m=a.size(); 38 | int n=b.size(); 39 | int l=0,r=m; 40 | while(l<=r){ 41 | int partx=l+(r-l)/2; 42 | int party=(m+n+1)/2-partx; 43 | int maxlx=(partx==0)?INT_MIN:a[partx-1]; 44 | int minrx=(partx==m)?INT_MAX:a[partx]; 45 | int maxly=(party==0)?INT_MIN:b[party-1]; 46 | int minry=(party==n)?INT_MAX:b[party]; 47 | if(maxlx<=minry&&maxly<=minrx){ 48 | if((m+n)%2==0) 49 | return (double)(max(maxlx,maxly)+min(minrx,minry))/2; 50 | else 51 | return (double)(max(maxlx,maxly)); 52 | }else if(maxlx>minry) 53 | r=partx-1; 54 | else 55 | l=partx+1; 56 | } 57 | return -1.0; 58 | } 59 | double findMedianSortedArrays(vector& nums1, vector& nums2) { 60 | if(nums1.size() 11 | using namespace std; 12 | 13 | vector findMedian(vector &arr, int n){ 14 | 15 | // To store the medians 16 | vector medians; 17 | 18 | // max heap 19 | priority_queue lo; 20 | 21 | //min heap 22 | priority_queue, greater> hi; 23 | 24 | for(int i = 0; i < n; i++){ 25 | 26 | int num = arr[i]; 27 | 28 | // Add to max heap 29 | lo.push(num); 30 | 31 | // Balancing step, that is inserting the current element at its position that is either less than median or more than median value 32 | hi.push(lo.top()); 33 | lo.pop(); 34 | 35 | // Maintain size property, as 'lo' can have utmost one more element than 'hi' or both have equal number of elements 36 | if (lo.size() < hi.size()) { 37 | lo.push(hi.top()); 38 | hi.pop(); 39 | } 40 | 41 | int median; 42 | 43 | // For odd number of elements 44 | if(lo.size() > hi.size()){ 45 | 46 | median = lo.top(); 47 | 48 | } 49 | // For even number of elements 50 | else{ 51 | 52 | median = (lo.top() + hi.top())/2; 53 | 54 | } 55 | 56 | medians.push_back(median); 57 | } 58 | 59 | return medians; 60 | 61 | } 62 | 63 | -------------------------------------------------------------------------------- /Arrays/MonotonicStack.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file MonotonicStack.cpp 3 | * @author Nisarg 4 | * @brief A monotonic stack is a stack whose elements are monotonically increasing or descreasing. 5 | * Sometimes we store the index of the elements in the stack and make sure the elements corresponding to those indexes in the stack forms a mono-sequence 6 | * 7 | * @question Find next smaller/greater element for each element in O(n) Time complexity. 8 | * 9 | */ 10 | 11 | 12 | #include 13 | using namespace std; 14 | 15 | vector nextGreaterElement(vector arr) { 16 | stack > stck; 17 | int i,n = arr.size(); 18 | vector ans(n); 19 | for(i=0;i1 20 | if(stck.empty()) { 21 | stck.push({arr[i], i}); 22 | continue; 23 | } 24 | while(!stck.empty() && stck.top().first < arr[i]) { 25 | ans[stck.top().second] = arr[i]; 26 | stck.pop(); 27 | } 28 | stck.push({arr[i],i}); 29 | } 30 | 31 | while(!stck.empty()) { 32 | ans[stck.top().second] = -1; 33 | stck.pop(); 34 | } 35 | return ans; 36 | } 37 | 38 | // Stack always array indices where values are in increasing order. 39 | vector nextSmallerElement(vector arr) { 40 | stack stck; 41 | int i,n = arr.size(); 42 | vector ans(n, -1); 43 | 44 | for(i=0;i arr = {1, 7, 2, 3, 1, 8}; 56 | 57 | vector nextGreater = nextGreaterElement(arr); 58 | cout << "\nNext Greater Element: "; 59 | for (auto ele: nextGreater) 60 | cout << ele << " "; 61 | vector nextSmaller = nextSmallerElement(arr); 62 | cout << "\nNext Smaller Element: "; 63 | for (auto ele: nextSmaller) 64 | cout << ele << " "; 65 | 66 | } -------------------------------------------------------------------------------- /Arrays/Sliding Window Max.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * https://leetcode.com/problems/sliding-window-maximum/solutions/5503612/best-code-in-c-must-see-easy-to-understand-beats-98-48-solution/ 3 | 4 | Find max value in each range of k size. 5 | */ 6 | -------------------------------------------------------------------------------- /Arrays/TrappingRainwater.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | class Solution { 5 | public: 6 | int trap(vector& height) { 7 | 8 | int n = height.size(); 9 | int left=0; int right=n-1; 10 | int res=0; 11 | int maxleft=0, maxright=0; 12 | 13 | while(left<=right){ 14 | 15 | if(height[left]<=height[right]){ 16 | 17 | if(height[left]>=maxleft) maxleft=height[left]; 18 | else res+=maxleft-height[left]; 19 | left++; 20 | } 21 | else{ 22 | 23 | if(height[right]>=maxright) maxright= height[right]; 24 | else res+=maxright-height[right]; 25 | right--; 26 | } 27 | } 28 | return res; 29 | } 30 | }; 31 | 32 | 33 | /* 34 | 35 | we are concerned with maximum height on left and that on right, 36 | so we can maintain two prefix and suffix arrays to precompute the max_left and max_right and the answer will be min(max_left,max_right) - curr_height 37 | But since we are only concerned with the minimum of the left and right max we can get rid of the extra space 38 | 39 | */ -------------------------------------------------------------------------------- /Arrays/readme.md: -------------------------------------------------------------------------------- 1 | Deletion in a vector takes O(1) time if order doesn't matter. 2 | Delete ith indexed value. 3 | 4 | ``` 5 | swap(arr[i], arr[n-1]); 6 | arr.pop_back(); 7 | ``` 8 | -------------------------------------------------------------------------------- /Bit-mask/Bitmask_Basic.cpp: -------------------------------------------------------------------------------- 1 | // Reference -> https://www.youtube.com/watch?v=7FmL-WpTTJ4 2 | // We are using bitmask to store the numbers between 1 and 10 (in integers) [Each bit represents a subset of intergers 1 to 10]. 15 represents set with 1,2,3,4.] 3 | // left shifting (x<>y) is equivalent to dividing x with 2^y. 5 | 6 | #include 7 | 8 | using namespace std; 9 | 10 | // If element is present it will get deleted and if its not there it will get added 11 | void erase_or_add(int n, int& subset) 12 | { 13 | subset = subset ^ 1<<(n-1); 14 | } 15 | void display(int subset) 16 | { 17 | cout<<"The subset is: "; 18 | // i is the ith bit from right to left 19 | // 0th bit represents 1 20 | for(int i=0;i<9;i++) 21 | { 22 | if(1< 11 | 12 | using namespace std; 13 | 14 | void LCS(string a, string b) { 15 | int n = a.size(), m = b.size(); 16 | 17 | vector > dp(n+1, vector (m+1, 0)); 18 | 19 | for(int i = 1; i <= n; i++) { 20 | for(int j = 1; j <= m; j++) { 21 | if(a[i-1] == b[j-1]) { 22 | dp[i][j] = dp[i-1][j-1] + 1; 23 | } 24 | else { 25 | dp[i][j] = max(dp[i-1][j], dp[i][j-1]); 26 | } 27 | cout << dp[i][j] << " "; 28 | } 29 | cout << endl; 30 | } 31 | 32 | cout << "Longest comman string's length is " << dp[n][m] << endl; 33 | 34 | int i = n+1, j = m+1; 35 | string ans = ""; 36 | while (i > 0 || j > 0) { 37 | if (a[i-1] == b[j-1]) { 38 | ans += a[i-1]; 39 | i--; j--; 40 | } 41 | else { 42 | if (dp[i-1][j] < dp[i][j-1]) 43 | j--; 44 | else 45 | i--; 46 | } 47 | } 48 | 49 | reverse(ans.begin(), ans.end()); 50 | cout << "Longest common subsequence is " << ans << endl; 51 | } 52 | 53 | void LCS_SpaceOptmized(string a, string b) { 54 | int n = a.size(), m = b.size(); 55 | 56 | vector dp(m+1, 0); 57 | vector prev(m+1, 0); 58 | 59 | for(int i = 1; i <= n; i++) { 60 | for(int j = 1; j <= m; j++) { 61 | if(a[i-1] == b[j-1]) { 62 | dp[j] = prev[j-1] + 1; 63 | } 64 | else { 65 | dp[j] = max(dp[j-1], prev[j]); 66 | } 67 | } 68 | prev = dp; 69 | } 70 | 71 | cout << "Longest comman string's length is " << prev[m] << endl; 72 | } 73 | 74 | int main() { 75 | 76 | string str1 = "abcda"; 77 | string str2 = "abcbcba"; 78 | 79 | int m = str1.length(); 80 | int n = str2.length(); 81 | 82 | LCS(str1, str2); 83 | LCS_SpaceOptmized(str1, str2); 84 | 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /DP/LIS.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Longest Increasing Subsequence 3 | Complexity for LIS Algo -> O(NlogN) 4 | N-number of elements 5 | */ 6 | 7 | #include 8 | using namespace std; 9 | 10 | // NOTE : aux is not necesserily the LIS but its length is same as LIS 11 | int length_LIS(int arr[], int n) 12 | { 13 | vector aux; //auxiliary vector stores the array elements likely to be LIS 14 | for(int i = 0; i < n; i++) 15 | { 16 | // Change lower_bound to upper_bound for non-decreasing subsequence 17 | auto itr = lower_bound(aux.begin(), aux.end(), arr[i]); 18 | if (itr == aux.end()) 19 | aux.push_back(arr[i]); // No element is larger than arr[i] 20 | else 21 | *itr = arr[i]; // replace the element in aux with elemwnt just smaller than it. 22 | } 23 | return aux.size(); 24 | 25 | } 26 | 27 | // This is O(n^2) soln which can be eventually used to find the the exact LIS 28 | int lengthLIS1(vector arr) { 29 | int n = arr.size(); 30 | vector dp(n, 1); // dp[i] = 1 as LIS can be itself 31 | 32 | for(int i=0; i dp(n, 1); // dp[i] = longest sub seq till i where ith element is part of it 44 | int ans = 0; 45 | 46 | for (int i = 0; i < n; i++) { 47 | for (int j = 0; j < i; j++) { 48 | if (arr[i] > arr[j]) 49 | dp[i] = max(dp[i], dp[j] + 1); 50 | } 51 | } 52 | 53 | for(int i = 0; i < n; i++) 54 | ans = max(ans, dp[i]); 55 | 56 | cout << "Length of LIS is " << ans << endl; 57 | } 58 | 59 | // Time Complexcity O(N log N) 60 | void find_LIS_Optimizd(int arr[],int n) 61 | { 62 | vector aux(n, 0); 63 | vector> parent(n); 64 | 65 | aux[0] = arr[0]; 66 | 67 | parent[0].push_back(arr[0]); 68 | int aux_size = 1; 69 | for (int i = 1; i < n; i++) { 70 | auto it =lower_bound(aux.begin(), aux.begin() + aux_size, arr[i]); 71 | 72 | if (it == aux.begin() + aux_size) { 73 | aux[aux_size] = arr[i]; 74 | 75 | parent[aux_size] = parent[aux_size - 1]; 76 | parent[aux_size].push_back(arr[i]); 77 | aux_size++; 78 | } 79 | else { 80 | if (*it != arr[i]) { 81 | aux[it- aux.begin()] = arr[i]; 82 | 83 | parent[it - aux.begin()][parent[it - aux.begin()].size() - 1] = arr[i]; 84 | } 85 | } 86 | } 87 | 88 | cout << "length " << aux_size << endl; 89 | 90 | for (auto x : parent[aux_size - 1]) { 91 | cout << x << " "; 92 | } 93 | } 94 | 95 | int main() 96 | { 97 | int arr[] = { 10, 22, 9, 33, 21, 50, 41, 60 }; 98 | int n= sizeof(arr)/sizeof(int); 99 | 100 | // Strictly increasing sub sequence 101 | cout << "Length of LIS is :" << length_LIS(arr,n) << endl; 102 | 103 | // Print the LIS 104 | length_LIS(arr,n); 105 | find_LIS(arr, n); 106 | } 107 | 108 | // Intersting question : 109 | // Given arr1[N], arr2[M] 1 2 | using namespace std; 3 | 4 | /* solution is based on gap strategy 5 | Reference --> https://www.youtube.com/watch?v=WpYHNHofwjc 6 | 7 | Every diagonal of the matrix can be uniquely identified by a gap value which represents the gap between i and j 8 | The gap 0 basically represents the individual elements which are themselves palindromes 9 | ex. str = abcda gaps = a | b | c | d | a ==> 4 gaps (cnt of |) 10 | Now for any particular i,j it is a palindrome if str from i+1 to j-1 is a palindrome and characters at i and j are equal 11 | So, dp[i][j] = dp[i+1][j-1] && str[i]==str[j] 12 | Here dp[i+1][j-1] represents the diagonally lower element which we have already computed in previous gap iterations 13 | 14 | */ 15 | 16 | class Solution { 17 | public: 18 | string longestPalindromeicSubString(string s) { 19 | int n = s.length(); 20 | bool dp[n][n]; 21 | memset(dp,false,sizeof(dp)); 22 | int start = -1; 23 | int end = -1; 24 | for(int gap=0;gap 9 | 10 | using namespace std; 11 | 12 | // Longest common sequence between two strings 13 | // If a[i] == b[j] dp[i][j] = dp[i-1][j-1] + 1; else max(dp[i-1][j], dp[i][j-1]) 14 | int LCS(string a, string b, int n, int m) 15 | { 16 | vector > dp(n + 1, vector(m + 1, 0)); 17 | for (int i = 1; i <= n; i++) 18 | { 19 | for (int j = 1; j <= m; j++) 20 | { 21 | if (a[i - 1] == b[j - 1]) 22 | dp[i][j] = 1 + dp[i - 1][j - 1]; 23 | else 24 | dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); 25 | } 26 | } 27 | return dp[n][m]; 28 | } 29 | 30 | // Trying to mimic the above code using same thing using two pointers 31 | int longestPalindromeSubseq(string str) 32 | { 33 | int i, j, n = str.size(); 34 | vector > dp(n + 1, vector(n + 1, 0)); // dp[i][j] denotes the string i to j (inclusive) 35 | for (i = n - 1; i >= 0; i--) 36 | { 37 | dp[i][i] = 1; 38 | for (j = i+1; j < n; j++) 39 | { 40 | dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]); 41 | if (str[i] == str[j]) 42 | { 43 | dp[i][j] = max(dp[i][j], dp[i + 1][j - 1] + 2); 44 | } 45 | } 46 | } 47 | return dp[0][n-1]; 48 | } 49 | 50 | // Optimized above solution to use O(N) space 51 | int longestPalndromeSubsequenceOptimzed(string str) { 52 | int n = str.size(); 53 | vector dp(n, 0), dpPrev(n, 0); // prev denotes the prev row of above solution. 54 | for (int i = n - 1; i >= 0; --i) { 55 | dp[i] = 1; 56 | for (int j = i+1; j < n; ++j) { 57 | if (str[i] == str[j]) { 58 | dp[j] = dpPrev[j-1] + 2; 59 | } else { 60 | dp[j] = max(dpPrev[j], dp[j-1]); 61 | } 62 | } 63 | dp.swap(dpPrev); 64 | } 65 | return dpPrev[n-1]; 66 | } 67 | 68 | int longestPalindromeSubseqUsingLCS(string s) 69 | { 70 | string s2 = s; 71 | reverse(s2.begin(), s2.end()); 72 | return LCS(s, s2, s.size(), s.size()); 73 | } 74 | 75 | int main() 76 | { 77 | string str = "abccefba"; 78 | cout << "Longest Palindromic subseq using LCS: " << longestPalindromeSubseqUsingLCS(str) << endl; 79 | cout << "Longest Palindromic subseq: " << longestPalindromeSubseq(str) << endl; 80 | cout << "Longest Palindromic subseq with O(N) Space Optmization: " << longestPalndromeSubsequenceOptimzed(str) << endl; 81 | } -------------------------------------------------------------------------------- /DP/MatrixChainMulti.cpp: -------------------------------------------------------------------------------- 1 | // We use this techinique when we have to put brackets in the given list based on some condn. 2 | // This solution is used when the order in which we pick a element determines the answer. 3 | 4 | // Very good que: https://leetcode.com/problems/burst-balloons/ 5 | -------------------------------------------------------------------------------- /DP/PalindromicCuts.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file PalindromicCut.cpp 3 | * @author Nisarg Gogate 4 | * @brief Cases when we want to divide array/string into parts and maximize/minimize 5 | * something about those parts. We can try MCM 6 | * 7 | * Ex. Find min numbers of cuts needed such that each substring is a palindrome. 8 | * @ref https://leetcode.com/problems/palindrome-partitioning-ii/description/ 9 | */ 10 | 11 | #include 12 | 13 | using namespace std; 14 | 15 | int SIZE = 2002; 16 | vector> dp(SIZE, vector(SIZE, -1)); 17 | 18 | bool isPalindrome(string str) 19 | { 20 | int i = 0, j = str.size() - 1; 21 | while (i < j) 22 | { 23 | if (str[i] != str[j]) 24 | return false; 25 | i++, j--; 26 | } 27 | return true; 28 | } 29 | 30 | /** 31 | * @brief Usually MCM time complexcity is O(n^3) but here as we are checking if it's 32 | * a palindrome time complexcity is O(n^4) 33 | */ 34 | int findCuts(string str, int l, int r) 35 | { 36 | if (dp[l][r] != -1) 37 | return dp[l][r]; 38 | 39 | // String can't be cut if it's length is already less than 1 40 | if (l >= r) 41 | return dp[l][r] = 0; 42 | 43 | if (isPalindrome(str.substr(l, r - l + 1))) 44 | return 0; 45 | 46 | int ans = r - l; 47 | 48 | // NOTE: k should not be equal to r to avoid inf loop 49 | for (int k = l; k < r; k++) 50 | { 51 | int left = dp[l][k] == -1 ? findCuts(str, l, k) : dp[l][k]; 52 | int right = dp[k + 1][r] == -1 ? findCuts(str, k + 1, r) : dp[k + 1][r]; 53 | 54 | ans = min(ans, left + right + 1); 55 | } 56 | return dp[l][r] = ans; 57 | } 58 | 59 | 60 | 61 | /** 62 | * @brief Idea is to find if a string is palindrom or not in O(1) using dp 63 | * Also, we don't really need to know number of plindromes between i and j. 64 | * 65 | * Here dp[i] represents number of palindromes from 0->i. 66 | * So, dp[i] = dp[k] + 1 where k->i is a plindrome. 67 | * 68 | * Time Complexcity: O(n^2), Space Complexcity: O(n^2) 69 | */ 70 | int findCutsOptimized(string str) { 71 | int n = str.size(); 72 | vector dp(n, 0); 73 | vector> isPalindrome(n, vector(n, false)); 74 | 75 | for (int len = 1; len <= n; ++len) { 76 | for (int i = 0; i <= n - len; ++i) { 77 | int j = i + len - 1; 78 | if (str[i] == str[j] && (len <= 2 || isPalindrome[i + 1][j - 1])) { 79 | isPalindrome[i][j] = true; 80 | } 81 | } 82 | } 83 | 84 | for (int i = 0; i < n; ++i) { 85 | if (isPalindrome[0][i]) { 86 | dp[i] = 0; 87 | } else { 88 | dp[i] = i; // suppose we need to cut at each index 89 | for (int j = 0; j < i; ++j) { 90 | if (isPalindrome[j + 1][i]) { 91 | dp[i] = min(dp[i], dp[j] + 1); 92 | } 93 | } 94 | } 95 | } 96 | 97 | return dp[n - 1]; 98 | } 99 | 100 | /** 101 | * @brief We take advantage of property that palindrome is same from front and back 102 | * We 103 | * 104 | * Time Complexcity: O(n^2), Space Complexcity: O(n) 105 | * 106 | * @param str 107 | * @return int 108 | */ 109 | int findCutsMostOptimized(string str) { 110 | int n = str.size(); 111 | vector dp(n+1); 112 | for (int i = 0; i <= n; i++) dp[i] = i-1; // note dp[0] will be set -1. This helps us with a cleaner code 113 | for(int mid = 0; mid < n; mid++){ 114 | //palindrome of odd lengths 1,3,5... 115 | for(int len = 0; mid-len >= 0 && mid+len < n; len++) 116 | if(str[mid-len] == str[mid+len]) 117 | dp[mid+len+1] = min(dp[mid+len+1], dp[mid-len]+1); 118 | //palindrome of even lengths 2,4,6... 119 | for(int len = 0; mid-len >= 0 && mid+len+1 < n; len++) 120 | if(str[mid-len] == str[mid+len+1]) 121 | dp[mid+len+2] = min(dp[mid+len+2], dp[mid-len]+1); 122 | } 123 | return dp[n]; 124 | 125 | } 126 | 127 | int main() 128 | { 129 | string str = "aabacd"; 130 | cout << "Minimum cuts needed " << findCuts(str, 0, str.size() - 1) << "\n"; 131 | } 132 | -------------------------------------------------------------------------------- /DP/digit_dp.cpp: -------------------------------------------------------------------------------- 1 | // Reference -> https://www.youtube.com/watch?v=heUFId6Qd1A 2 | // F(x) returns boolean value 3 | // General -> How many integers x in range [0,R] obey F(x) 4 | // Example -> Find cnt of numbers betn L and R which have a sum of digits = x 5 | // 1 <= L <= R <= 10^18 6 | // 1 <= X <= 180 7 | #include 8 | using namespace std; 9 | 10 | // Max no of dights in a number be 100(Not needed) 11 | int dp[101][181][2]; 12 | // boolena value tight stores checks if we can place any number at indx(R.size()-n) or we need we can place till ub 13 | int digit_dp(string R,int n,int sum,bool tight) 14 | { 15 | if(sum < 0) 16 | return 0; 17 | if(n==0) 18 | { 19 | if(sum == 0) 20 | return 1; 21 | return 0; 22 | } 23 | 24 | if(dp[n][sum][tight] != -1) 25 | return dp[n][sum][tight]; 26 | 27 | // ub is upper bound till which digit we can use at that particular index 28 | int ub = 9,ans=0; 29 | if(tight) 30 | ub = (R[R.size()-n]-'0'); 31 | for(int i=0;i<=ub;i++) 32 | { 33 | // Once a number is non tight it won't ever be tight in future 34 | // A tight will be tight only if we keep on passing the higest number possible at that indx 35 | ans += digit_dp(R,n-1,sum-i,tight&(i==ub)); 36 | } 37 | return dp[n][sum][tight] = ans; 38 | } 39 | 40 | int main() 41 | { 42 | string L = ""; 43 | string R = "490447834749"; 44 | int x = 20; 45 | memset(dp,-1,sizeof dp); 46 | cout< https://www.youtube.com/watch?v=QukpHtZMAtM&list=PLb3g_Z8nEv1icFNrtZqByO1CrWVHLlO5g&index=4 2 | // Reference -> https://www.thecrazyprogrammer.com/2017/05/travelling-salesman-problem.html 3 | // Time Complexcity -> O(n^2 * 2^n) 4 | // Space Complexcity -> O(2^n * n) 5 | // NOTE : Whenever we feel a need to pass a subset of set we can use this technique of digit dp 6 | // Que. Find minimum distance to travel if travellers wishes to visit every city atleast once and reach back to his starting location at the end 7 | #include 8 | using namespace std; 9 | 10 | #define MAX 9999 11 | 12 | int n=4; // Number of the places want to visit 13 | 14 | //Next distan array will give Minimum distance through all the position 15 | int distan[10][10] = { 16 | {0, 10, 15, 20}, 17 | {10, 0, 35, 25}, 18 | {15, 35, 0, 30}, 19 | {20, 25, 30, 0} 20 | }; 21 | 22 | int all_visited = (1< 2 | // Time Complexity: O(V + E) 3 | // A slight modification of question: Find 2nd fastest way of reaching from source to destination. in Undirected ascyclic graph. 4 | // Fastest way is using normal BFS. Here we'll ne two dist arrays. dist1[]stroring 1st time we encounter a num. dist2[] we encountering 2nd time. 5 | //https://www.youtube.com/watch?v=_rnQKrA9xzA&t=436s&ab_channel=codestorywithMIK 6 | using namespace std; 7 | #define LIM 1007 8 | 9 | vector adj[LIM]; 10 | // vector dist(LIM,-1); 11 | // vector parent(LIM,-1); 12 | int visited[LIM]; 13 | 14 | void addEdge(int u, int v) 15 | { 16 | adj[u].push_back(v); 17 | adj[v].push_back(u); 18 | } 19 | 20 | void bfs(int src) 21 | { 22 | queue q; 23 | int d=0; 24 | // dist[src] = d; 25 | // parent[src] = -1; 26 | q.push(src); 27 | visited[src]=true; 28 | while(!q.empty()) 29 | { 30 | int u = q.front(); 31 | q.pop(); 32 | 33 | cout<>V>>E; 56 | 57 | 58 | for(i=0;i>u>>v; 62 | addEdge(u,v); 63 | } 64 | 65 | 66 | cout<<"Enter source node for iterative bfs: "; 67 | cin>>src; 68 | cout<<"BFS=> "; 69 | bfs(src); 70 | cout< https://www.youtube.com/watch?v=FtN3BYH2Zes 3 | Minimum distance of src from every other node present in graph 4 | Complexity for Bellman Ford's Algo -> O(E*V) 5 | E-Edges V-Vertices 6 | */ 7 | #include 8 | #define LIM 3000 9 | #define INF 1e5+3 10 | 11 | using namespace std; 12 | 13 | 14 | //NOTE: Here reprentation of graph is done a bit differnetly 15 | typedef pair pii; 16 | 17 | vector> G(LIM,vector(3)); 18 | vector min_dist(LIM,INF); 19 | int V,E; 20 | 21 | /* 22 | IMP NOTE: If there is a cycle with total sum negative then this algo WON'T WORK 23 | We baically relax the edges V-1 times 24 | */ 25 | void bellman_ford(int src) 26 | { 27 | min_dist[src] = 0; 28 | int u,v,k; 29 | for(k=0;k min_dist[u]+wt) 49 | { 50 | cout << "There is a negtive cycle\n"; 51 | break; 52 | } 53 | } 54 | 55 | } 56 | 57 | int main() 58 | { 59 | int i,src=0,u,v,wt; 60 | 61 | cout<<"Enter number of vertices and edges: "; 62 | cin>>V>>E; 63 | cout<>u>>v>>wt; 69 | 70 | G[i][0] = u; 71 | G[i][1] = v; 72 | G[i][2] = wt; 73 | } 74 | 75 | cout<<"Enter the source node: "; 76 | cin>>src; 77 | bellman_ford(src); 78 | cout< 2 | 3 | using namespace std; 4 | #define LIM 1007 5 | typedef enum {WHITE,GREY,BLACK} col; 6 | // we try ro color whole graph in 2 colors grey and black 7 | 8 | 9 | vector adj[LIM]; 10 | vector color(LIM,WHITE); 11 | 12 | 13 | void addEdge(int u, int v) 14 | { 15 | adj[u].push_back(v); 16 | adj[v].push_back(u); 17 | } 18 | 19 | void bfs() 20 | { 21 | queue q; 22 | int d=0; 23 | 24 | for(int i=1;i>V>>E; 78 | 79 | 80 | for(i=0;i>u>>v; 84 | addEdge(u,v); 85 | } 86 | 87 | 88 | // Printing color of each node in graph 89 | bfs(); 90 | 91 | 92 | 93 | } -------------------------------------------------------------------------------- /Graph/Bipartite_matching.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Bipartite_matching.cpp 3 | * @author Nisarg 4 | * @brief Question: Given n job appplicants and m jobs. Given ith applicant with letter from jth job 5 | * Find maximum number of job applicants which can get a job. jobs[i][j] = 1 / 0 6 | * 7 | * @ref: https://www.geeksforgeeks.org/maximum-bipartite-matching/ 8 | * @ref: https://cp-algorithms.com/graph/kuhn_maximum_bipartite_matching.html 9 | * @ref: https://leetcode.com/problems/maximum-number-of-accepted-invitations/solutions/1978859/python-hungarian-algorithm-easy-to-understand/ 10 | */ 11 | 12 | #include 13 | 14 | using namespace std; 15 | 16 | int jobs = 6, applicants = 6; 17 | 18 | vector > G; 19 | vector currentMatching(jobs, -1); // Job i mapped with currentMatching[i] applicant. 20 | vector visited(applicants); // Usual use so that dfs doesn't visit same vertex again 21 | 22 | /** 23 | * Main idea behind the logic is a job applicant will only leave job if he/she gets some other job. 24 | * 25 | * @return bool : true a new match is added 26 | */ 27 | 28 | bool findMaxBiPartiteMatching(int u) // applicant 29 | { 30 | if (visited[u]) // if applicant is already assigned or checked no need to recheck 31 | return false; 32 | 33 | visited[u] = true; 34 | 35 | // Checking if vth job if already selected by some applicant 36 | for (auto v : G[u]) { 37 | // if current matching is available for v or if v can find some other job 38 | // checking if selected applicant for job v can find some other job 39 | if ( currentMatching[v] == -1 || findMaxBiPartiteMatching(currentMatching[v]) ) { 40 | currentMatching[v] = u; 41 | return true; 42 | } 43 | } 44 | return false; 45 | } 46 | 47 | int main() 48 | { 49 | G = { 50 | {1, 2}, // Applicant 0 has {1, 2} job offers 51 | {0, 3}, // Applicant 1 has {0, 3} job offers 52 | {2}, 53 | {2, 3}, 54 | {}, 55 | {5} 56 | }; 57 | 58 | int ans = 0; 59 | for (int applicant = 0; applicant < applicants; applicant++) 60 | { 61 | visited.assign(applicants, false); 62 | if(findMaxBiPartiteMatching(applicant)) 63 | ans++; 64 | } 65 | 66 | cout << "Max num of G matching with applicants is " << ans; 67 | } 68 | -------------------------------------------------------------------------------- /Graph/DFS.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | We can peform multisorurce bfs also for the problems of type 4 | 1. there are k hospitals and n cities and they are connected so find closest hostila form each city 5 | Add all hospitals as src and do bfs on unvisited nodes so ... 6 | 7 | Time Complexity: O(V + E) 8 | 9 | */ 10 | #include 11 | #define LIM 3000 12 | #define INF 1e5+3 13 | using namespace std; 14 | 15 | vector adj[LIM]; 16 | bool visited[LIM]; 17 | 18 | void addEdge(int u, int v) 19 | { 20 | adj[u].push_back(v); 21 | adj[v].push_back(u); 22 | } 23 | 24 | void dfs_iterative(int src) 25 | { 26 | memset(visited,0,sizeof(visited)); 27 | stack stck; 28 | stck.push(src); 29 | 30 | while(stck.size()) 31 | { 32 | int u=stck.top(); 33 | stck.pop(); 34 | 35 | visited[u]=true; 36 | cout<>V>>E; 73 | 74 | 75 | for(i=0;i>u>>v; 79 | addEdge(u,v); 80 | } 81 | 82 | 83 | cout<<"Enter source node for iterative dfs: "; 84 | cin>>src; 85 | cout<<"Iterative_DFS=> "; 86 | dfs_iterative(0); 87 | cout<>src; 91 | cout<<"Recursive_DFS=> "; 92 | } 93 | -------------------------------------------------------------------------------- /Graph/FloydWarshall.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file FloydWarshall.cpp 3 | * @author Nisarg 4 | * @brief Multi Source shortest path algorithm. Find shortest paths from all nodes to all other nodes. 5 | * Logic: dist[i][j] = min (dist[i][j]],dist[i][k] + dist[k][j]) 6 | * Time complexity: O(V^3) 7 | * @date 2024-07-28 8 | */ 9 | 10 | #define INF 1e5+3 11 | 12 | #include 13 | 14 | using namespace std; 15 | 16 | void findShortestDist(vector>& matrix) { 17 | int n = matrix.size(), i, j, k; 18 | 19 | // initialize matrix with INF dist where no roads are available 20 | // initialize matrix with 0 dist where i == j 21 | for (i = 0; i < n; i++) { 22 | for (j = 0; j < n; j++) { 23 | if (matrix[i][j] == -1) matrix[i][j] = INF; 24 | if (i == j) matrix[i][j] = 0; 25 | } 26 | } 27 | 28 | // Floyd Warshall's algorithm 29 | for(k = 0; k < n; k++) 30 | for(i = 0; i < n; i++) 31 | for(j = 0; j < n; j++) 32 | matrix[i][j] = min(matrix[i][j], matrix[i][k] + matrix[k][j]); 33 | } 34 | 35 | 36 | int main() { 37 | int V = 4; 38 | vector > matrix(V, vector(V, -1)); 39 | matrix[0][1] = 2; 40 | matrix[1][0] = 1; 41 | matrix[1][2] = 3; 42 | matrix[3][0] = 3; 43 | matrix[3][1] = 5; 44 | matrix[3][2] = 4; 45 | 46 | findShortestDist(matrix); 47 | 48 | 49 | cout << "Following matrix shows the shortest distances between every pair of vertices \n"; 50 | for (int i = 0; i < V; i++) { 51 | for (int j = 0; j < V; j++) { 52 | if (matrix[i][j] == INF) 53 | cout << "INF "; 54 | else 55 | cout << matrix[i][j] << " "; 56 | } 57 | cout << endl; 58 | } 59 | } -------------------------------------------------------------------------------- /Graph/README.md: -------------------------------------------------------------------------------- 1 | # Graphs 2 | 3 | Minimum Spanning Tree 4 | - **Prim's Algorithm**: Add `{wt, node}` to min heap to visit all nodes only once. 5 | 6 | 7 | Shortest Distance from `src` node to all nodes in Graph 8 | - **Dijkstra Algorithm**: Greedy approach choose the closest node from each node and store in min heap. *[+ve weights]*. 9 | - **Bellman Ford**: Loop V times over all edges in graph and set `dist[v] = min(dist[v], dist[u]+wt(u,v))`. *[-ve weights]* 10 | 11 | Shortest Distance between all pairs of nodes in Graph 12 | - **Floyd Warshall Algorithm**: For every path which passes through k, `dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])` 13 | 14 | Dungeon Break: https://leetcode.com/problems/dungeon-game/description/ Really good question 15 | -------------------------------------------------------------------------------- /Graph/cycleDetection.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file cycleDetection.cpp 3 | * @author Nisarg 4 | * @date 2024-07-27 5 | * 6 | * Detect cycle in directed and adirected graphs 7 | */ 8 | 9 | #include 10 | #define LIM 1007 11 | 12 | using namespace std; 13 | 14 | vector G[LIM]; 15 | 16 | // Other way of doing this is by bipartiate coloring 17 | bool isCyclicInDirectedGraph(int n, vector inDegree) { 18 | 19 | int i; 20 | queue q; // NOTE: it stores the topo sorted order 21 | 22 | for(i=0;i> n >> edges; 51 | 52 | vector inDegree(n); 53 | 54 | for(int i=0;i> u >> v; 56 | G[u].push_back(v); 57 | inDegree[v]++; 58 | } 59 | 60 | if(isCyclicInDirectedGraph(n, inDegree)) 61 | cout << "Cycle found in directed Graph" << endl; 62 | } -------------------------------------------------------------------------------- /Graph/dijkstra.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | A minimum distance of src from every other node present in graph with all non-negative weights (optimized algo) OR Negative weighted a-cyclic graph (Non-optimized Algo) 3 | Complexity for dijktra's Algo -> O((V + E) log V) 4 | E-Edges V-Vertices 5 | 6 | We may add same node multiple times, hence total elements in a heap might be E. Hence, log(E). 7 | Intreasting thing is to E = V*(V-1) => 2*log(V). 8 | 9 | Slight modification: Think of adding a virtual node which joins an edge to each node. [Similar to multi source BFS] 10 | 11 | Dikjtras can be applied 3-4 times... you reverse graph... node a to src and dest dist 12 | https://leetcode.com/problems/minimum-weighted-subgraph-with-the-required-paths/description/ 13 | */ 14 | #include 15 | #define LIM 3000 16 | #define INF 1e5+3 17 | typedef pair pii; 18 | using namespace std; 19 | 20 | //NOTE: Global variables are initailized to 0 21 | vector adj[LIM]; 22 | vector min_dist(LIM,INF); 23 | 24 | //Each node in adj list represnts vertex and weight 25 | void addEdge(int u, int v, int wt) 26 | { 27 | adj[u].push_back({v,wt}); 28 | adj[v].push_back({u,wt}); 29 | } 30 | 31 | void dijktra(int src) 32 | { 33 | //MIN HEAP 34 | // Keep distace or weight in first plce and indx in second 35 | priority_queue, greater > pq; 36 | 37 | for(int i=0;i min_dist[curr]) 52 | continue; 53 | 54 | for(auto u : adj[curr]) 55 | { 56 | int next = u.first; 57 | int d = u.second; 58 | 59 | //If previous distance is more than the new distance 60 | if(min_dist[next] > min_dist[curr]+d) 61 | { 62 | pq.push({ d + min_dist[curr], next }); 63 | min_dist[next] = d+ min_dist[curr]; 64 | } 65 | } 66 | } 67 | 68 | } 69 | 70 | int main() 71 | { 72 | int V,i,E,src,u,v,wt; 73 | 74 | cout<<"Enter number of vertices and edges: "; 75 | cin>>V>>E; 76 | cout<>u>>v>>wt; 82 | addEdge(u,v,wt); 83 | } 84 | 85 | cout<<"Enter the source node: "; 86 | cin>>src; 87 | dijktra(src); 88 | cout< 17 | #define LIM 3000 18 | #define INF 1e5+3 19 | using namespace std; 20 | 21 | typedef pair pii; 22 | vector adj[LIM]; 23 | bool visited[LIM]; 24 | 25 | //Each node in adj list represnts vertex and weight 26 | void addEdge(int u, int v, int wt) 27 | { 28 | adj[u].push_back({v,wt}); 29 | adj[v].push_back({u,wt}); 30 | } 31 | 32 | int prim() 33 | { 34 | //MIN HEAP 35 | priority_queue, greater > pq; 36 | 37 | int mst_sum=0; 38 | int curr_dist=0; 39 | 40 | //Lets assume we start from 0th node 41 | pq.push({curr_dist,0}); 42 | 43 | while(pq.size()) 44 | { 45 | //we get the smallest possible distance on top of pq 46 | int curr_node=pq.top().second; 47 | int curr_dist=pq.top().first; 48 | 49 | pq.pop(); 50 | 51 | //if already visited the it must be connected to smallest possible value 52 | if(visited[curr_node]) 53 | continue; 54 | 55 | visited[curr_node]=true; 56 | mst_sum += curr_dist; 57 | 58 | for(auto u : adj[curr_node]) 59 | { 60 | //We push in all the possible adjecent nodes from curr_node 61 | if(!visited[u.first]) 62 | pq.push({u.second,u.first}); 63 | } 64 | } 65 | return mst_sum; 66 | } 67 | 68 | int main() 69 | { 70 | int V,E,i,src,u,v,wt; 71 | 72 | cout<<"Enter number of vertices and edges: "; 73 | cin>>V>>E; 74 | cout<>u>>v>>wt; 80 | addEdge(u,v,wt); 81 | } 82 | 83 | 84 | cout<<"Minimum spanning tree sum: "; 85 | cout< https://cses.fi/problemset/task/1679 5 | Time complexcity -> O(V+E) 6 | Space Complexcity -> O(V) 7 | */ 8 | 9 | 10 | // Alternate approach can be looking at the in-degree of each node 11 | // Step 1: Find in-degree of each node and maintain it in an array 12 | // step 2: if(indgree[i] == 0) put in queue (bfs) and add it in aur ans array 13 | // do bfs and which ever element we visit reduce its indegree 14 | // keep on checking while reducing indegree and if its zero add... REPEAT 15 | 16 | #include 17 | #define LIM 3000 18 | #define INF 1e5+3 19 | typedef enum {WHITE,GREY,BLACK} col; //white-no col 20 | 21 | using namespace std; 22 | 23 | int V,E; 24 | vector G[LIM]; 25 | vector visited(LIM,false); 26 | vector color(LIM,WHITE); 27 | 28 | bool notIsCyclic(int u) 29 | { 30 | color[u] = GREY; 31 | 32 | bool ans=true; 33 | 34 | for(auto v:G[u]) 35 | { 36 | if(color[v] == GREY) 37 | return false; 38 | if(color[v] == BLACK) 39 | continue; 40 | 41 | ans &= notIsCyclic(v); 42 | 43 | } 44 | color[u] = BLACK; 45 | return ans; 46 | } 47 | 48 | void dfs(int u, stack& stck) 49 | { 50 | visited[u] = true; 51 | for(auto v: G[u]) 52 | if(!visited[v]) 53 | dfs(v,stck); 54 | // NOTE : We insert element in stack after its dfs traversal. 55 | stck.push(u); 56 | } 57 | 58 | int main() 59 | { 60 | int i,j; 61 | cin>>V>>E; 62 | 63 | for(i=0;i> u >> v; 67 | G[u].push_back(v); 68 | } 69 | 70 | // Check for any cycle in graph 71 | for(i=1;i<=V;i++) 72 | if(color[i] == WHITE) 73 | if(!notIsCyclic(i)) 74 | { 75 | cout << "IMPOSSIBLE\n"; 76 | return; 77 | } 78 | 79 | // Adding elements to the stack if not visited 80 | stack stck; 81 | for(i=1;i<=V;i++) 82 | if(!visited[i]) 83 | dfs(i,stck); 84 | 85 | // Actually elements are adding in opposite order of topo sort but we 86 | // acces the elements in descending order as its a stack. 87 | for(;!stck.empty();stck.pop()) 88 | cout << stck.top() << " "; 89 | 90 | 91 | } -------------------------------------------------------------------------------- /Graph/union_find_algo.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Que: Given a list of operation makeFriends(a,b) and areFriends(a,b) 3 | These methods makes a and b friends or checks if they are friends. 4 | Time & Space complexcity if done by Graph O(n) & O(n) 5 | Time & Space complexcity in case of disjoint set O(m*4) & O(n) 6 | : m is the number of operations being performed on this dijoint set 7 | https://leetcode.com/problems/the-earliest-moment-when-everyone-become-friends 8 | Ref: https://www.youtube.com/watch?v=Kptz-NVA2RE 9 | */ 10 | 11 | #include 12 | 13 | using namespace std; 14 | 15 | vector parent; // Keeps track of group representative/parent 16 | vector sz; // Keeps track of num of elements in children below this node 17 | 18 | // Init the array with each element as it's parent 19 | void init(int n) 20 | { 21 | parent.resize(n); 22 | sz.resize(n); 23 | for (int i = 0; i < n; i++) 24 | { 25 | parent[i] = i; 26 | sz[i] = 1; 27 | } 28 | } 29 | 30 | // Finds parent of x then parent of parent of x and so on... 31 | // Along with path compression as on return it updates parent[x] 32 | int find(int x) 33 | { 34 | if (parent[x] == x) 35 | return x; 36 | 37 | return parent[x] = find(parent[x]); // remember to call it for parent[x] 38 | } 39 | 40 | // Joins sets of x to y. Based on the rank of parent for minimum time complexcity. 41 | void weightedUnion(int x, int y) 42 | { 43 | int xRoot = find(x); 44 | int yRoot = find(y); 45 | 46 | if (xRoot == yRoot) 47 | return; 48 | 49 | if (sz[xRoot] < sz[yRoot]) 50 | { 51 | parent[xRoot] = yRoot; 52 | sz[yRoot] += sz[xRoot]; 53 | } 54 | else 55 | { 56 | parent[yRoot] = xRoot; 57 | sz[xRoot] += sz[yRoot]; 58 | } 59 | 60 | } 61 | 62 | // n - number of fiends 63 | // m - number of operations/relations 64 | int main() 65 | { 66 | int i, n, m; 67 | 68 | cin >> n >> m; 69 | init(n); 70 | for (i = 0; i < m; i++) 71 | { 72 | string operation; 73 | int x, y; 74 | cin >> operation >> x >> y; 75 | if (operation == "makeFriend") 76 | { 77 | weightedUnion(x, y); 78 | } 79 | else if (operation == "isFriend") 80 | { 81 | if(find(x) == find(y)) cout << "Yes\n"; 82 | else cout << "No\n"; 83 | } 84 | } 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /Greedy or DP (Problems)/Continuous_subarray_sum.cpp: -------------------------------------------------------------------------------- 1 | // Link --> https://leetcode.com/problems/continuous-subarray-sum/ 2 | Find if is there any subarray with sum in multiple of k 3 | 4 | bool find(vector arr, int k){ 5 | set s; 6 | int sum=0; 7 | for(int i=0;i https://leetcode.com/problems/maximum-profit-in-job-scheduling/ 2 | 3 | // You're given the startTime, endTime and profit arrays, return the maximum profit 4 | // you can take such that there are no two jobs in the subset with overlapping time range. 5 | // 1 <= startTime[i] < endTime[i] <= 10^9 6 | 7 | // NOT A GREEDY SOLN 8 | int jobScheduling(vector& startTime, vector& endTime, vector& profit) { 9 | int n = startTime.size(); 10 | vector> jobs; 11 | for (int i = 0; i < n; ++i) { 12 | jobs.push_back({endTime[i], startTime[i], profit[i]}); 13 | } 14 | 15 | // Sort according to end time of jobs 16 | sort(jobs.begin(), jobs.end()); 17 | 18 | // dp[i] stores maximum profit at time = i 19 | map dp = {{0, 0}}; 20 | for (auto& job : jobs) { 21 | // Finding the profit at largets end time before current job's start iem 22 | int cur = prev(dp.upper_bound(job[1]))->second + job[2]; 23 | if (cur > dp.rbegin()->second) 24 | dp[job[0]] = cur; 25 | } 26 | return dp.rbegin()->second; 27 | } 28 | 29 | 30 | // Link -->https://practice.geeksforgeeks.org/problems/job-sequencing-problem-1587115620/1# 31 | // N jobs takes 1 unit of time to complete and jth job has job[j] as deadline. 32 | // Find max profit? 33 | 34 | /* 35 | * Sort according to the profits (decreasing) 36 | * Do the process as late as possible (Close to deadline) 37 | * U have the ans... 38 | */ -------------------------------------------------------------------------------- /Greedy or DP (Problems)/Kadane.cpp: -------------------------------------------------------------------------------- 1 | // Find max_sum of sub array 2 | // Question? Why should curr_sum start with arr[i] and not with something before ith index? 3 | // Assume started from start => Case 1: (some -ve sum) + arr[j] - we will already started from arr[j]. 4 | => Case 2: (Some +ve sum) + arr[j] - It's already part of curr_sum. 5 | int kadane(vector arr) { 6 | int n = arr.size(),i,ans_sum=0,curr_sum = arr[0]; 7 | for(i=1;i arr) { 17 | int ans = arr[0],max_val=arr[0],min_val=arr[0]; 18 | for(int i=1;i arr) { 34 | int i,n=arr.size(),prev_max = 0,ans=0; 35 | // TRICK - arr[i]+i + arr[j]-j is to be maximized 36 | for(i=0;i Time Complexcity O(n logn) 6 | */ 7 | #include 8 | using namespace std; 9 | 10 | // Return The sequence which satisfies the given condition 11 | vector> queue_reconstruction(vector> people) { 12 | // Observations - 13 | // We need to count people with height taller or equal to in front of them 14 | // Smaller person is completely irrelevant 15 | // For smallest person all persons are greater than him 16 | sort(people.begin(),people.end(),[](pair p1,pair p2){ 17 | return p1.first>p2.first or 18 | (p1.first == p2.first and p1.second> ans; 22 | 23 | for(int i=0;i 6 | using namespace std; 7 | 8 | int min_jump(vector arr) 9 | { 10 | int n = arr.size(),i; 11 | int range_of_jump = arr[0]; // This is the index upto which we can reach 12 | int max_reachable_index = arr[0]; // Next maximum reachable index from current range (1 more jump will be neede) 13 | int jump = 1; 14 | 15 | // We have already made our 1st jump 16 | for(i=1;i> n; 34 | vector arr(n); 35 | for(auto &it:arr) 36 | cin >> it; 37 | 38 | cout << min_jump(arr) << "\n"; 39 | } -------------------------------------------------------------------------------- /Greedy or DP (Problems)/variations.txt: -------------------------------------------------------------------------------- 1 | 1. Find maximum no. of intervals to select with no overlap. (Jump Scheduling - I) 2 | --> Jump Problem (DP but like Kedans) 3 | 4 | 5 | 2. Find minimum no. of intervals to select with minimum overlap. (Jump -II) 6 | --> DP solution (Job Scheduling problem) 7 | 8 | 9 | 3. Find maximum no. of intervals which overlap at a point? (Maximum no. of train platforms problem) 10 | --> Use a counter variable and add 1 when an interval starts and subtract 1 when an interval ends. 11 | max of counter is ans. -------------------------------------------------------------------------------- /Matrix or Backtracking(Problems)/Max_Submatrix_with_LT_Ksum.cpp: -------------------------------------------------------------------------------- 1 | // Maximum size square Sub-Matrix with sum less than or equals to K 2 | // Link -> geeksforgeeks.org/maximum-size-square-sub-matrix-with-sum-less-than-or-equals-to-k/ 3 | 4 | // Step 1: Find Prefix matrix sum[i][j] = arr[i-1][j-1]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1] 5 | // Step 2: Iterate over all i and j (N^2) 6 | // Step 3: Do binary search over all possible square sizes. min(i,j); 7 | // Step 4: Check if square sum is less than equals to k 8 | 9 | 10 | // Dungeon Game Reach n,m from 1,1 and healtmust be always +ve while moving. 11 | // Find starting health 12 | // https://leetcode.com/problems/dungeon-game/ 13 | 14 | // Crux --> start from n-1,m-1 boz we need to know what will be elements next to know what to choose 15 | -------------------------------------------------------------------------------- /NumberTheory/RandomNum.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file RandomNum.cpp 3 | * @author Nisarg Gogate 4 | * 5 | * Finding random number between 0 and n-1 6 | * 1. rand() % n - It gives a random number but it's not evenly distributed. 7 | * 2. double num = rand() / RAND_MAX; 8 | * num * n-1 will be truly random. 9 | * 10 | * Q. Find weighted random number index based on the weight. 11 | * https://leetcode.com/problems/random-pick-with-weight/ 12 | * As we can't really add number multiple times to array (space issue), 13 | * we can add it as a prefix sum. look at this prefix sum from left. we see a array same 14 | * as the adding number multiple times. Getting numbe in (log n) with lower_bound. 15 | */ 16 | 17 | #include 18 | using namespace std; 19 | 20 | class Solution { 21 | public: 22 | vector prefix; 23 | 24 | Solution(vector& w) { 25 | prefix.push_back(w[0]); 26 | for(int i=1;i 13 | using namespace std; 14 | 15 | class LRUCache 16 | { 17 | int capacity; 18 | list> dq; // key, value pair 19 | 20 | // store references of key in cache 21 | unordered_map>::iterator> mp; 22 | 23 | public: 24 | LRUCache(int capacity) 25 | { 26 | this->capacity = capacity; 27 | } 28 | 29 | int get(int key) 30 | { 31 | if (mp.find(key) == mp.end()) 32 | return -1; 33 | 34 | int value = mp[key]->second; 35 | dq.erase(mp[key]); 36 | dq.push_front({key, value}); 37 | mp[key] = dq.begin(); 38 | 39 | return value; 40 | } 41 | 42 | void put(int key, int value) 43 | { 44 | if (mp.find(key) == mp.end()) 45 | { 46 | if (dq.size() == capacity) 47 | { 48 | pair last = dq.back(); 49 | dq.pop_back(); 50 | mp.erase(last.first); 51 | } 52 | } 53 | else 54 | { 55 | dq.erase(mp[key]); 56 | } 57 | dq.push_front({key, value}); 58 | mp[key] = dq.begin(); 59 | } 60 | }; 61 | 62 | // Driver Code 63 | int main() 64 | { 65 | LRUCache ca(4); 66 | 67 | ca.put(1, 2); 68 | ca.put(2, 3); 69 | ca.put(3, 2); 70 | ca.put(1, 2); 71 | cout << ca.get(4) << "\n"; 72 | ca.put(4, 1); 73 | cout << ca.get(4) << "\n"; 74 | ca.put(5, 6); 75 | return 0; 76 | } -------------------------------------------------------------------------------- /Quick Revise Documents/Recursion_BackTracking.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisarg0/Algorithm-Implementation/1214f458b5b66e4babeac498d72ed405de2d3b93/Quick Revise Documents/Recursion_BackTracking.pdf -------------------------------------------------------------------------------- /Quick Revise Documents/System-Design-educative.io.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisarg0/Algorithm-Implementation/1214f458b5b66e4babeac498d72ed405de2d3b93/Quick Revise Documents/System-Design-educative.io.pdf -------------------------------------------------------------------------------- /Quick Revise Documents/Trees_Part_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisarg0/Algorithm-Implementation/1214f458b5b66e4babeac498d72ed405de2d3b93/Quick Revise Documents/Trees_Part_1.pdf -------------------------------------------------------------------------------- /Quick Revise Documents/Trees_Part_2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisarg0/Algorithm-Implementation/1214f458b5b66e4babeac498d72ed405de2d3b93/Quick Revise Documents/Trees_Part_2.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Algorithm Implementations 2 | 3 | We have not written all of these algos ourselves. This is merely a small collection of easy and beautiful solutions to complex problems. We have added reference links and questions on top of each file for further references. Feel free to star mark and fork :D 4 | 5 | ``` 6 | Common time complexities 7 | 8 | Let n be the main variable in the problem. 9 | 10 | If n ≤ 12, the time complexity can be O(n!). 11 | If n ≤ 25, the time complexity can be O(2n). 12 | If n ≤ 100, the time complexity can be O(n4). 13 | If n ≤ 500, the time complexity can be O(n3). 14 | If n ≤ 104, the time complexity can be O(n2). 15 | If n ≤ 106, the time complexity can be O(n log n). 16 | If n ≤ 108, the time complexity can be O(n). 17 | If n > 108, the time complexity can be O(log n) or O(1). 18 | ``` 19 | 20 | ## Features 21 | - Quick access to segregated codes. 22 | - Easy to understand yet small solutions. 23 | - Tries | Segment Trees (Trees), LRU Cache (OS). 24 | 25 | ## Authors 26 | 27 | - [Nisarg](https://github.com/nisarg0) 28 | - [Diplesh](https://github.com/dips4982) 29 | 30 | **Special Thanks to all the youtubers for the free and awesome content!!!** 31 | 32 | - [Katik Arora](https://www.youtube.com/user/MrHulasingh25) 33 | - [Utkarsh Gupta](https://www.youtube.com/channel/UCGS5ZzcSAymQbWZvNoKOFhQ) 34 | - [take U forward](https://www.youtube.com/channel/UCJskGeByzRRSvmOyZOz61ig) 35 | - [Pep-coding](https://www.youtube.com/channel/UC7rNzgC2fEBVpb-q_acpsmw) 36 | 37 | 38 | ## Support 39 | 40 | If you find some error do rasie issue [here](https://github.com/nisarg0/algos_implementation/issues). 41 | 42 | For support, email nisarggogate212@gmail.com or dipleshmankape@gmail.com 43 | 44 | 45 | -------------------------------------------------------------------------------- /Range_queries/Mo's_algo.cpp: -------------------------------------------------------------------------------- 1 | // Find number of elements ocuuring only once in range [L,R]. -------------------------------------------------------------------------------- /Range_queries/Persisitant tree.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisarg0/Algorithm-Implementation/1214f458b5b66e4babeac498d72ed405de2d3b93/Range_queries/Persisitant tree.cpp -------------------------------------------------------------------------------- /Range_queries/Range_Update(Difference_Array).cpp: -------------------------------------------------------------------------------- 1 | // Reference link -> https://www.geeksforgeeks.org/difference-array-range-update-query-o1/ 2 | // Range update in time complexity O(1) and space complexity O(n) 3 | // Prefixsum and sufix sum is also a important technique but can be helpful only if 4 | // the operation in range is invertible(Ex add,sub or mul,div) can't be used for min,max or exor,and 5 | #include 6 | 7 | using namespace std; 8 | const int LIM = 1e3; 9 | vector difference(LIM,0); 10 | 11 | void init(int arr[],int n) 12 | { 13 | // 0th indx is init with value of 0th element in arr 14 | difference[0] = arr[0]; 15 | // after that nothinng should be added (precaution) 16 | difference[n] = 0; 17 | for(int i=1;in-1 or l>r) return; 25 | // we add x to lth indx so indirectly we add x to everthing after it 26 | difference[l] += x; 27 | // we need to subtract x from all the elements after r 28 | difference[r+1] -= x; 29 | } 30 | 31 | void print(int arr[], int n) 32 | { 33 | arr[0] = difference[0]; 34 | 35 | for(int i=1;i O(N) 6 | 2. Range sum query -> O(logN) for each level we only visit not more than four vertices 7 | 3. Update query -> O(logN) 8 | */ 9 | 10 | #include 11 | #define LIM 1007 12 | using namespace std; 13 | 14 | 15 | int arr[LIM]; //input array 16 | int seg[4*LIM]={0}; //Seg tree children for index i are 2*i and 2*i+1 17 | int lazy[4*LIM]={0}; //lazy tree children for index i are 2*i and 2*i+1 18 | 19 | //initialization of segment tree 20 | void init_tree(int node_indx,int node_lower,int node_upper) 21 | { 22 | if(node_lower == node_upper) 23 | { 24 | seg[node_indx] = arr[node_upper]; 25 | return ; 26 | } 27 | 28 | int mid=(node_lower+node_upper)/2; 29 | 30 | init_tree(node_indx*2, node_lower, mid); 31 | init_tree(node_indx*2+1, mid+1, node_upper); 32 | 33 | seg[node_indx]=seg[2*node_indx]+seg[2*node_indx+1]; 34 | } 35 | 36 | // a,b is the range of query node_lower,node_upper is the range for particular node in seg_tree 37 | //a<=b and node_lower<=node_upper 38 | int range_query(int node_indx, int a, int b, int node_lower, int node_upper) 39 | { 40 | //range is between a,b 41 | if(a<=node_lower and node_upper<=b) 42 | return seg[node_indx]; 43 | 44 | //Not in range 45 | if(bnode_upper) 46 | return 0; //INT_MIN in case of min query 47 | 48 | int mid=(node_lower+node_upper)/2; 49 | 50 | //Intersecting on left side or right side or both 51 | return range_query(2*node_indx,a,b,node_lower,mid) + 52 | range_query(2*node_indx+1,a,b,mid+1,node_upper); 53 | } 54 | 55 | 56 | //updatepoint at a 57 | void update_point(int node_indx,int a,int node_lower, int node_upper, int val) 58 | { 59 | if(node_upper == node_lower) 60 | { 61 | seg[node_indx]+=val; 62 | return; 63 | } 64 | 65 | if(a < node_lower or a>node_upper) 66 | return ; 67 | 68 | int mid=(node_lower+node_upper)/2; 69 | 70 | // if a is between lower and mid 71 | if(node_lower >= a and a <= mid) 72 | update_point(2*node_indx,a,node_lower,mid,val); 73 | else 74 | update_point(2*node_indx+1,a,mid+1,node_upper,val); 75 | 76 | seg[node_indx]=seg[2*node_indx]+seg[2*node_indx+1]; 77 | } 78 | 79 | // a,b is the range of query node_lower,node_upper is the range for particular node in seg_tree 80 | // change values in range[a,b] by +val 81 | // make a copy of seg_tree called lazy and init with 0 82 | 83 | /*void update_query(int node_indx,int a, int b, int node_lower, int node_upper, int val) 84 | { 85 | //we need to update changes in lower levels of this node 86 | if(lazy[node_indx]!=0) 87 | { 88 | seg[node_indx]+=(node_upper-node_lower+1)*val; 89 | if(node_upper!=node_lower) 90 | { 91 | lazy[node_indx*2]+=lazy[node_indx]; 92 | lazy[node_indx*2+1]+=lazy[node_indx]; 93 | } 94 | lazy[node_indx]=0; 95 | } 96 | 97 | //out of range 98 | if(bnode_upper or node_lower>node_upper ) return; 99 | 100 | //required range is between the range of segtree 101 | if(node_lower<=a and node_upper<=b) 102 | { 103 | seg[node_indx]+=(node_upper-node_lower+1)*val; 104 | if(node_lower!=node_upper) 105 | { 106 | lazy[node_indx*2]+=lazy[node_indx]; 107 | lazy[node_indx*2+1]+=lazy[node_indx]; 108 | } 109 | return; 110 | } 111 | 112 | //Intersecting on left side or right side or both 113 | int mid=(node_lower+node_upper)/2; 114 | update_query(2*node_indx,a,b,node_lower,mid,val); 115 | update_query(2*node_indx+1,a,b,mid+1,node_upper,val); 116 | 117 | seg[node_indx]=seg[node_indx*2]+seg[node_indx*2+1]; 118 | }*/ 119 | 120 | 121 | int main() 122 | { 123 | int i; 124 | //Intializing an array of size 10 with index itself 125 | //NOTE: We have used 1 based indexing 126 | for(i=1;i<=10;i++) 127 | { 128 | arr[i]=i; 129 | } 130 | 131 | //Initilize the Seg tree 132 | init_tree(1,1,10); 133 | 134 | //Range query[a,b] 135 | int a,b,val; 136 | cout<<"SUM: Enter range a,b: "; 137 | cin>>a>>b; 138 | cout<>a>>b; 145 | cout<>val; 147 | for(i=a;i<=b;i++) 148 | { 149 | update_point(1,i,1,10,val); 150 | } 151 | 152 | //Range query[a,b] 153 | cout<<"SUM: Enter range a,b: "; 154 | cin>>a>>b; 155 | cout< https://www.youtube.com/watch?v=2EpX9LkO2T0 2 | // Refernece -> https://youtu.be/0jWeUdxrGm4 3 | // NOTE : We can't update efficiently 4 | // Precomutation- O(NLogN) Query - O(LogN) 5 | // If query Function asked is Idempotent(F(a,a)=a) we can solve 1 query in O(1*op). op is time taken by the operator(gcd takes more time) 6 | // ex. max(a,a)=a , min, gcd, bitwie-or, bitwise-and, etc. 7 | 8 | #include 9 | using namespace std; 10 | 11 | // #define int long long 12 | 13 | const int LIM = (int)1e7; 14 | const int K = (int)(25); 15 | 16 | 17 | // jth column in ith row represents the value of function from i to i+2^j. 18 | // st[i][j] = f(i to i+2^j) 19 | int st[LIM][K+1]; //30 = log2 LIM 20 | 21 | int f(int a, int b) 22 | { 23 | return min(a,b); 24 | } 25 | 26 | // range [i,i+2^j−1] of length 2^j splits nicely into 27 | // the ranges [i,i+2^(j−1)−1] and [i+2^(j−1),i+2^(j−1)], both of length 2^(j−1). 28 | void init(int arr[],int n) 29 | { 30 | // length of ruery is 1 31 | for (int i = 0; i < n; i++) 32 | st[i][0] = arr[i]; 33 | 34 | // j length query and strts from i 35 | for (int j = 1; j <= K; j++) 36 | for (int i = 0; i + (1 << (j-1)) <= n; i++) // Note : the loop termination condn. 37 | st[i][j] = f(st[i][j-1], st[i + (1 << (j - 1))][j - 1]); 38 | } 39 | 40 | int query_normal(int l,int r) 41 | { 42 | int ans = INT_MAX; 43 | // from 2^30m till 2^0 whch are the numbers we can subtract from r-l+1 till its not 0 44 | // we basically add values of set bits from st. 45 | for(int i=K;i>=0;i--) 46 | { 47 | if((1< 5 | 6 | using namespace std; 7 | 8 | // Generates heap from ith node and it's children. 9 | void heapify(vector &arr, int n, int i) 10 | { 11 | int largest = i; // Initialize largest as root 12 | int l = 2 * i + 1; // left = 2*i + 1 13 | int r = 2 * i + 2; // right = 2*i + 2 14 | 15 | // If left child is larger than root 16 | if (l < n && arr[l] > arr[largest]) 17 | largest = l; 18 | 19 | // If right child is larger than largest so far 20 | if (r < n && arr[r] > arr[largest]) 21 | largest = r; 22 | 23 | // If largest is not root 24 | if (largest != i) { 25 | swap(arr[i], arr[largest]); 26 | 27 | // Recursively heapify the affected sub-tree 28 | heapify(arr, n, largest); 29 | } 30 | } 31 | 32 | // main function to do heap sort 33 | void heapSort(vector &arr, int n) 34 | { 35 | // Build heap (rearrange array) 36 | // We did this from n/2-1 -> 0 b'coz for a complete binary tree last n/2 elements are leave nodes. 37 | for (int i = n / 2 - 1; i >= 0; i--) 38 | heapify(arr, n, i); 39 | 40 | // Now arr is a max heap 41 | // Pass by ref 42 | 43 | // One by one extract an element from heap 44 | for (int i = n - 1; i > 0; i--) { 45 | // Move current root to end 46 | swap(arr[0], arr[i]); 47 | 48 | // call max heapify on the reduced heap 49 | heapify(arr, i, 0); 50 | } 51 | } 52 | 53 | void print(vector arr){ 54 | cout << "Sorted Array is : "; 55 | for(int i=0;i arr{10,3,2,5,7}; 63 | 64 | heapSort(arr,n); 65 | 66 | print(arr); 67 | } 68 | -------------------------------------------------------------------------------- /Sorting Algorithms/Inbuilt_sorting_algos.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | // Keep variables static to avoid some error 6 | bool compare(int a, int b){ 7 | return a Insertion Sort 16 | // 16 < n < 2log(n) --> Quick Sort 17 | // 2log(n) < n --> Merge Sort 18 | sort(arr,arr+n); 19 | 20 | // Decreasing sort 21 | sort(arr,arr+n,greater<>()); 22 | // Alternate and better 23 | // sort(arr+n,arr); 24 | 25 | // Sort using comparator 26 | sort(arr,arr+n,compare); 27 | 28 | // Stable sorting using merge sort 29 | // O(n*log^2(n)) if memory is not availabe else O(nlog(n)) 30 | stable_sort(arr,arr+n); 31 | 32 | for(int i=0;i 5 | 6 | using namespace std; 7 | // Merges 2 arrays [lo,mid], [mid+1,hi] 8 | void merge(vector &arr,int lo, int hi, int mid){ 9 | int i = lo,j = mid+1; 10 | vector ans; 11 | 12 | while(i <= mid or j <= hi){ 13 | int l = i > mid ? INT_MAX : arr[i]; // is not in range take INT_MAX 14 | int r = j > hi ? INT_MAX : arr[j]; 15 | 16 | if(l &arr, int lo, int hi) { 27 | if(lo>=hi) 28 | return; 29 | 30 | int mid = (lo+hi)/2; 31 | mergeSort(arr,lo,mid); 32 | mergeSort(arr,mid+1,hi); 33 | 34 | merge(arr,lo,hi,mid); 35 | } 36 | 37 | void print(vector arr){ 38 | cout << "Sorted Array is : "; 39 | for(int i=0;i arr = {3,6,1,2,10,7,8,5,9,0}; 47 | 48 | mergeSort(arr,0,n-1); 49 | print(arr); 50 | } -------------------------------------------------------------------------------- /Sorting Algorithms/O(n^2)_Algos.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // Insertion Sort 5 | // We divide an array into 2 parts one is sorted and other is original array 6 | // Size of first part keeps on increasing by 1 in each iteration and min value is put there 7 | void insertionSort(vector &arr){ 8 | int n=arr.size(),i,j; 9 | for(i=0;i arr[j] swap them. 25 | void selectionSort(vector &arr){ 26 | int n=arr.size(),i,j; 27 | for(i=0;i arr[j]) 30 | swap(arr[i],arr[j]); 31 | } 32 | 33 | // Bubble Sort 34 | // Like a bubble move largest element to top 35 | // keep on swapping adjacent elements 36 | void bubbleSort(vector &arr){ 37 | int n = arr.size(),i,j; 38 | for(i=0;i arr[j+1]) 41 | swap(arr[j],arr[j+1]); 42 | } 43 | 44 | // Stops the comparison when the array is sorted 45 | void modified_bubbleSort(vector &arr){ 46 | int i,j,n=arr.size(); 47 | bool isSorted = false; 48 | for(i=0;i arr[j+1]){ 52 | isSorted = false; 53 | swap(arr[j],arr[j+1]); 54 | } 55 | } 56 | } 57 | } 58 | 59 | void print(vector arr){ 60 | cout << "Sorted Array is : "; 61 | for(int i=0;i arr = {3,6,1,2,10,7,8,5,9,0}; 69 | 70 | // bubbleSort(arr); 71 | // modified_bubbleSort(arr); 72 | insertionSort(arr); 73 | // selectionSort(arr); 74 | print(arr); 75 | } -------------------------------------------------------------------------------- /Sorting Algorithms/QuickSort.cpp: -------------------------------------------------------------------------------- 1 | // O(nlog(n)) --> average time Complexcity 2 | // O(n^2) --> worst case (If 1st element is chosen as pivot and arr is sorted) 3 | // O(1) --> Extra Space 4 | // Link --> https://www.hackerearth.com/practice/algorithms/sorting/quick-sort/tutorial/ 5 | // Link --> https://www.youtube.com/watch?v=if40LxQ8_Xo&t=1171s 6 | 7 | #include 8 | using namespace std; 9 | // All ements to the left of pivot are less than pivot and to the right are greater 10 | // It means the element is in its sorted position 11 | int partition(vector &arr, int lo, int hi){ 12 | int j,i = lo+1; 13 | int pivot = arr[lo]; // We try to find index of pivot 14 | /* 15 | arr[lo] is our pivot 16 | Our array lo to hi is divided into 3 regions: 17 | [lo+1,j-1] --> Less than Pivot 18 | [j,i-1] --> More than Pivot 19 | [i,hi] --> Unchecked 20 | */ 21 | 22 | for(j=lo+1;j<=hi;j++){ 23 | if(arr[j] < pivot){ 24 | swap(arr[i],arr[j]); 25 | i++; 26 | } 27 | } 28 | // i-1 is largest index with no. less than pivot 29 | // So it is pivot index 30 | swap(arr[lo],arr[i-1]); 31 | return i-1; 32 | } 33 | 34 | // Divide and Conquer Algo 35 | void quickSort(vector &arr, int lo, int hi){ 36 | if(lo>=hi) 37 | return; 38 | int pivot_index = partition(arr,lo,hi); 39 | quickSort(arr,lo,pivot_index-1); 40 | quickSort(arr,pivot_index+1,hi); 41 | } 42 | 43 | void print(vector arr){ 44 | cout << "Sorted Array is : "; 45 | for(int i=0;i arr = {3,6,1,2,10,7,8,5,9,0}; 53 | 54 | quickSort(arr,0,n-1); 55 | print(arr); 56 | } -------------------------------------------------------------------------------- /Sorting Algorithms/RadixSort.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | // Time Complexcity = O(d*n) 5 | // where d is max no. of digits in a number and n is size of ar 6 | // Ref -> https://www.youtube.com/watch?v=a5e7RgCdel0 7 | 8 | // Question -> Max Gap Leetcode 9 | // We use pegion hole principle + Radix Sort to get ans in O(n) time. 10 | 11 | // elements inside a bucket = (max_val-min_val)/n-1; 12 | // Note bucket index (freq_index here) can be caluclated as (arr[i]-min)/interval 13 | void countSort(vector& arr, int exp) { 14 | vector freq(10,0); 15 | vector ans(arr.size()); 16 | 17 | for(int i=0;i prefix_index(10,0); 21 | for(int i=0;i<10;i++){ 22 | prefix_index[i] = freq[i]; 23 | if(i != 0) 24 | prefix_index[i] += prefix_index[i-1]; 25 | } 26 | 27 | // To convert this prefix arr to index arr 28 | // Each value in prefix[i] represnts max index of i 29 | for(int i=0;i=0;i--){ 34 | int index = (arr[i]/exp)%10; 35 | ans[prefix_index[index]] = arr[i]; 36 | prefix_index[index]--; 37 | } 38 | 39 | arr = ans; 40 | } 41 | 42 | // Works for +ve elements 43 | void radixSort(vector &arr){ 44 | int i,max_val = INT_MIN; 45 | for(i=0;i arr){ 58 | cout << "\nSorted Array is : "; 59 | for(int i=0;i arr = {4533,6534,5881,2896,104,7435,8236,7865,909,6450}; 67 | 68 | radixSort(arr); 69 | print(arr); 70 | } 71 | -------------------------------------------------------------------------------- /Sorting Algorithms/cycleSort.cpp: -------------------------------------------------------------------------------- 1 | // Given array of size n has elements from 0 to n-1. 2 | // Sorting can be done in O(n) using cycleSort 3 | #include 4 | 5 | using namespace std; 6 | 7 | void cycleSort(vector& arr, int n) { 8 | int i = 0; 9 | 10 | while(i arr){ 19 | cout << "Sorted Array is : "; 20 | for(int i=0;i arr{2,3,4,1,0}; 28 | 29 | cycleSort(arr,n); 30 | 31 | print(arr); 32 | } -------------------------------------------------------------------------------- /Strings/KMP.cpp: -------------------------------------------------------------------------------- 1 | // String comapre Algo with O(m+n) m,n being lenghts of string to compare 2 | 3 | /* 4 | * IDEA - Is prefix of pattern again apperaring somewhere again in the pattern. 5 | * Ref Link --> https://www.youtube.com/watch?v=V5-7GzOfADQ 6 | */ 7 | 8 | /* 9 | * Indices : 0 1 2 3 4 5 6 7 8 9 10 | * Pattern : a b c d a b e a b c 11 | * Lps : - - - 1 2 1 2 3 Rest all the values are 0 12 | 13 | * Each index in lps represents the index the pointer has to move once once the char in text doesn't match with char in pattern 14 | */ 15 | 16 | #include 17 | 18 | using namespace std; 19 | 20 | // pietable 21 | // Longest proper Prefix which is also Suffix 22 | void computeLPSArray(char* pat, int M, int* lps) 23 | { 24 | // length of the previous longest prefix suffix 25 | int len = 0; 26 | 27 | lps[0] = 0; // lps[0] is always 0 28 | 29 | // the loop calculates lps[i] for i = 1 to M-1 30 | int i = 1; 31 | while (i < M) { 32 | if (pat[i] == pat[len]) { 33 | len++; 34 | lps[i] = len; 35 | i++; 36 | } 37 | else // (pat[i] != pat[len]) 38 | { 39 | // This is tricky. Consider the example. 40 | // AAACAAAA and i = 7. The idea is similar 41 | // to search step. 42 | if (len != 0) { 43 | len = lps[len - 1]; 44 | 45 | // Also, note that we do not increment 46 | // i here 47 | } 48 | else // if (len == 0) 49 | { 50 | lps[i] = 0; 51 | i++; 52 | } 53 | } 54 | } 55 | } 56 | 57 | 58 | // Prints occurrences of txt[] in pat[] 59 | vector KMPSearch(char* pat, char* txt) 60 | { 61 | vector ans; 62 | int M = strlen(pat); 63 | int N = strlen(txt); 64 | 65 | // create lps[] that will hold the longest prefix suffix 66 | // values for pattern 67 | int lps[M]; 68 | 69 | // Preprocess the pattern (calculate lps[] array) 70 | computeLPSArray(pat, M, lps); 71 | 72 | int i = 0; // index for txt[] 73 | int j = 0; // index for pat[] 74 | while (i < N) { 75 | if (pat[j] == txt[i]) { 76 | j++; 77 | i++; 78 | } 79 | 80 | if (j == M) { 81 | ans.push_back(i-j); 82 | j = lps[j - 1]; 83 | } 84 | 85 | // mismatch after j matches 86 | else if (i < N && pat[j] != txt[i]) { 87 | // Do not match lps[0..lps[j-1]] characters, 88 | // they will match anyway 89 | if (j != 0) 90 | j = lps[j - 1]; 91 | else 92 | i = i + 1; 93 | } 94 | } 95 | return ans; 96 | } 97 | 98 | 99 | 100 | int main(){ 101 | // 0 based indexing 102 | char txt[] = "ABABDABACDABABCABAB"; 103 | char pat[] = "ABABCABAB"; 104 | vector matched_indx = KMPSearch(pat, txt); 105 | 106 | cout << "pattern appears from following indices: "; 107 | for(auto indx : matched_indx) 108 | cout << indx << " "; 109 | } -------------------------------------------------------------------------------- /Strings/PatternMatching.cpp: -------------------------------------------------------------------------------- 1 | // Given a large text and a pattern where text >> pattern. 2 | // Find indices for the matching pattern in the text. 3 | 4 | // Rolling hash method: O(n) time, O(1) space 5 | 6 | /** 7 | * @brief Rolling hash method 8 | * hash(pattern) = 9 | * hash(pattern[0..m-1]) = (pattern[0]*d^(m-1) + pattern[1]*d^(m-2) + ... + pattern[m-1]) mod q 10 | * Also, First character of the pattern is the most significant character hence it's mutiplied by d^(m-1) 11 | * 12 | * 13 | * Formula for Rehashing text in O(1) operation given hash of previous window: 14 | * hash( txt[s+1 .. s+m] ) = ( d ( hash( txt[s .. s+m-1]) – txt[s]*h ) + txt[s + m] ) mod q 15 | * 16 | * NOTE: 17 | * d: Number of characters in the alphabet 18 | * q: A prime number 19 | * h: d^(m-1) mod q 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | using namespace std; 28 | 29 | int findModuloPower(int a, int b, int q) { 30 | int result = 1; 31 | while( b > 0) { 32 | if (b & 1) { 33 | result = (result * a) % q; 34 | } 35 | b = b >> 1; 36 | a = (a * a) % q; 37 | } 38 | return result%q; 39 | } 40 | 41 | // Find hash of any string 42 | int findStringHash(int d, int h,int q, string str) { 43 | int strHash = 0; 44 | for (int i = 0; i < str.size(); i++) { 45 | strHash = (d * strHash + str[i]) % q; 46 | } 47 | return strHash; 48 | } 49 | 50 | 51 | vector findMatches(string text, string pattern) { 52 | int d = 256; // Number of characters in the alphabet 53 | int q = 10007; // A prime number 54 | 55 | int n = text.size(); 56 | int m = pattern.size(); 57 | 58 | int h = findModuloPower(d, m-1, q); // d^(m-1) mod q 59 | 60 | int patternHash = findStringHash(d, h, q, pattern); 61 | int textHash; 62 | 63 | vector startIndicesOfMatches; 64 | 65 | for (int i = 0; i <= n - m; i++) { 66 | // Don't need to rehash the pattern 67 | if(i == 0) 68 | textHash = findStringHash(d, h, q, text.substr(0, m)); 69 | else // Rehash the text 70 | textHash = (d * (textHash - text[i - 1] * h) + text[i + m - 1]) % q; 71 | 72 | // In case of negative hash, make it positive 73 | if (textHash < 0) 74 | textHash = textHash + q; 75 | 76 | 77 | if (patternHash == textHash) { 78 | bool isMatch = true; 79 | // In case of collision, check if the strings are actually equal 80 | for (int j = 0; j < m; j++) { 81 | if (text[i + j] != pattern[j]) { 82 | isMatch = false; 83 | break; 84 | } 85 | } 86 | if (isMatch) { 87 | startIndicesOfMatches.push_back(i); 88 | } 89 | } 90 | } 91 | } 92 | 93 | int main() { 94 | string text = "AABAACAADAABAABA"; 95 | string pattern = "AABA"; 96 | 97 | 98 | auto startIndicesOfMatches = findMatches(text, pattern); 99 | 100 | cout << "Indices of matches: "; 101 | for (auto index : startIndicesOfMatches) { 102 | cout << index << " "; 103 | } 104 | } 105 | 106 | 107 | /** 108 | * @brief Addition to this problem: 109 | * Find number of unique substring in a string 110 | * - Get hash for all substrings of length m (O(n*n)) 111 | * - Store them in a set and get the size of set 112 | * 113 | * This method will mostly work as probablity of collision is approx: 1/q ie. 1/10007 = 0.0001% 114 | * if we increase q to 10^9 then probablity of collision will be 0.000000001% 115 | * 116 | * Read more : https://cp-algorithms.com/string/string-hashing.html#determine-the-number-of-different-substrings-in-a-string 117 | * 118 | * It can be improved by using larger q (10^18) and using a good hash function 119 | */ -------------------------------------------------------------------------------- /Strings/string_input.cpp: -------------------------------------------------------------------------------- 1 | // If the input format of a string is know... 2 | // Ex.str = "233+923i" How to extract numbers 3 | 4 | #include 5 | using namespace std; 6 | 7 | int main(){ 8 | 9 | string str = "233+923i"; 10 | int a,b; 11 | sscanf(str.c_str(), "%d+%di", &a, &b); 12 | cout << a << " " << b << endl; 13 | 14 | //********************************* OR *********************************** 15 | 16 | str = "I am Nisarg and I love DS-Algo"; 17 | vector vec; 18 | 19 | istringstream iss(str); 20 | for(string s;iss >> s;) 21 | vec.push_back(s); 22 | 23 | for(int i=0;ihttps://www.codechef.com/LTIME98B/problems/LGSEG 9 | // If an array is to be divided into many segments have a try if binary lifting can help somhow 10 | 11 | 12 | #include 13 | const int LIM = (int)2e5+3; 14 | 15 | using namespace std; 16 | 17 | // elements of trees are stored from 0 18 | vector tree[LIM]; 19 | vector parent(LIM); 20 | vector depth(LIM); 21 | // up(i,j) stores element 2^j steps above (element)i. 22 | int up[LIM][20]; 23 | 24 | void addEdge(int u, int v) 25 | { 26 | tree[u].push_back(v); 27 | tree[v].push_back(u); 28 | } 29 | 30 | // Precomputes the up using dp. 31 | void binary_lifting(int u, int pa) 32 | { 33 | // up by 2^0 steps 34 | up[u][0] = pa; 35 | 36 | for(int i=1;i<20;i++) 37 | { 38 | if(up[u][i-1] != -1) 39 | up[u][i] = up[ up[u][i-1] ][i-1]; 40 | else 41 | up[u][i] = -1; 42 | } 43 | 44 | // Vanilla dfs 45 | for(auto v: tree[u]) 46 | if(v != pa) 47 | binary_lifting(v,u); 48 | } 49 | 50 | // returns the node_val at dist h above node 51 | // if no node is present returns -1 52 | int getKthAncestor(int node, int h) 53 | { 54 | // node should not be -1 55 | for(int i=0;i<20 and node != -1;i++) 56 | { 57 | // if ith bit of h is set 58 | if(h & 1<=0;k--) 81 | { 82 | if(up[a][k] != up[b][k]) 83 | { 84 | a = up[a][k]; 85 | b = up[b][k]; 86 | } 87 | } 88 | 89 | // we have reached one level below of LCA 90 | return up[a][0]; 91 | } 92 | 93 | int main() 94 | { 95 | int i,src,u,v,q,x,k,V; 96 | 97 | cout<<"Enter number of vertices: "; 98 | cin>>V; 99 | 100 | for(i=0;i>u>>v; 104 | addEdge(u,v); 105 | } 106 | 107 | src = 0; 108 | binary_lifting(src,-1); 109 | 110 | cout<<"Enter number of queries: "; 111 | cin>>q; 112 | 113 | for(i=0;i> x >> k; 116 | cout << "Node :" << getKthAncestor(x,k) << " is at a dist " 117 | << k << "from " << x << endl; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /Trees/LCA.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | class TreeNode 5 | { 6 | public: 7 | int val; 8 | TreeNode *left, *right; 9 | }; 10 | 11 | // Assuming the given 2 nodes always exist 12 | TreeNode* LCA_binaryTree(TreeNode* root, int n1, int n2) { 13 | if(!root) 14 | return NULL; 15 | if(root->val == n1 || root->val == n2) 16 | return root; 17 | 18 | TreeNode* left_lca = LCA_binaryTree(root->left,n1,n2); 19 | TreeNode* right_lca = LCA_binaryTree(root->right,n1,n2); 20 | 21 | // if both left and right gives a ptr then root must be LCA 22 | if(left_lca and right_lca) 23 | return root; 24 | // Left must give LCA 25 | if(left_lca) 26 | return left_lca; 27 | else 28 | return right_lca; 29 | } 30 | // For special case of BST 31 | TreeNode* LCA_bst(TreeNode* root, int n1, int n2) { 32 | if(!root) 33 | return NULL; 34 | if(n1 < root->val and n2 < root->val) 35 | return LCA_bst(root->left,n1,n2); 36 | if(n1 > root->val and n2 > root->val) 37 | return LCA_bst(root->right,n1,n2); 38 | 39 | // n1 < root->val and n2 > root->val 40 | return root; 41 | } 42 | 43 | 44 | // -------------------------------- Helpers --------------------- 45 | 46 | TreeNode* newNode(int val) 47 | { 48 | TreeNode* Node = new TreeNode(); 49 | Node->val = val; 50 | Node->left = Node->right = NULL; 51 | return(Node); 52 | } 53 | 54 | int main(){ 55 | TreeNode *root = newNode(20); 56 | root->left = newNode(8); 57 | root->right = newNode(22); 58 | root->left->left = newNode(4); 59 | root->left->right = newNode(12); 60 | root->left->right->left = newNode(10); 61 | root->left->right->right = newNode(14); 62 | 63 | int n1 = 10, n2 = 14; 64 | TreeNode *t = LCA_binaryTree(root, n1, n2); 65 | cout << "LCA of " << n1 << " and " << n2 << " is " << t->val<val< 2 | using namespace std; 3 | 4 | // Problem Link : https://leetcode.com/problems/word-search-ii/ 5 | // Code taken from : https://gist.github.com/SuryaPratapK/6329c354704632725dccc7ec5900d199 6 | 7 | class Solution { 8 | struct node{ //TrieNode 9 | char c; 10 | int ends; 11 | string word; 12 | node *child[26]; 13 | }; 14 | struct node *getNode(char c) //get newnode 15 | { 16 | node *newnode = new node; 17 | newnode->c = c; 18 | newnode->ends = 0; 19 | newnode->word = ""; 20 | for(int i=0;i<26;++i) 21 | newnode->child[i] = NULL; 22 | return newnode; 23 | } 24 | node *root = getNode('/'); //root 25 | 26 | //Trie INSERT 27 | void insert(string s) 28 | { 29 | node *curr=root; 30 | int index,i=0; 31 | while(s[i]) 32 | { 33 | index = s[i]-'a'; 34 | if(curr->child[index]==NULL) 35 | curr->child[index] = getNode(s[i]); 36 | 37 | curr=curr->child[index]; 38 | i+=1; 39 | } 40 | curr->ends += 1; 41 | curr->word = s; 42 | } 43 | 44 | void solve(vector>& board,int i,int j,int r,int c,vector& ans,node *curr) 45 | { 46 | //Base case 47 | //If the trie doesn't have the current char OR cell is Visited 48 | int index = board[i][j]-'a'; 49 | if(board[i][j]=='$' || curr->child[index]==NULL) 50 | return; 51 | 52 | curr = curr->child[index]; 53 | if(curr->ends > 0) 54 | { 55 | ans.push_back(curr->word); 56 | curr->ends -=1; 57 | } 58 | 59 | //Body 60 | char ch = board[i][j]; //Store current char 61 | board[i][j] = '$'; //Mark current node visited 62 | 63 | if(i>0) //TOP 64 | solve(board,i-1,j,r,c,ans,curr); 65 | if(i0) //LEFT 68 | solve(board,i,j-1,r,c,ans,curr); 69 | if(j findWords(vector>& board, vector& words) { 77 | int r=board.size(); 78 | int c=board[0].size(); 79 | 80 | //Insert all words in TRIE 81 | for(int i=0;i ans; 86 | for(int i=0;i https://www.geeksforgeeks.org/trie-memory-optimization-using-hash-map/ 2 | // NOTE : 3 | 4 | #include 5 | using namespace std; 6 | 7 | 8 | const int LIM = (int)1e7; 9 | const int K = (int)(25); 10 | 11 | typedef struct trie_tag{ 12 | bool isEnd; 13 | map mp; 14 | 15 | trie_tag(){isEnd = false;} 16 | }trie; 17 | 18 | // Global delecration of root pointing to null 19 | trie * root = NULL; 20 | 21 | void insert(string str) 22 | { 23 | if(root == NULL) 24 | root = new trie; 25 | 26 | trie* curr = root; 27 | 28 | for(char ch : str) 29 | { 30 | if(curr -> mp.find(ch) == curr -> mp.end()) 31 | curr -> mp[ch] = new trie; 32 | // As we want to move inside that part of trie 33 | curr = curr -> mp[ch]; 34 | } 35 | curr -> isEnd = true; 36 | } 37 | 38 | bool search(string str) 39 | { 40 | trie *curr = root; 41 | 42 | if(curr == NULL) 43 | return false; 44 | 45 | for(char ch : str) 46 | { 47 | if(!curr -> mp[ch]) 48 | return false; 49 | // As we want to move inside that part of trie 50 | curr = curr -> mp[ch]; 51 | } 52 | return curr -> isEnd; 53 | } 54 | 55 | // bool delete(string str) 56 | // { 57 | // return 0; 58 | // } 59 | 60 | int main(void) 61 | { 62 | vector arr = {"AABAC","AAB","ABC","AEFDH","BCD"}; 63 | 64 | for(auto it: arr) 65 | insert(it); 66 | 67 | if(search("AEFD")) 68 | cout << "PRESENT\n"; 69 | else 70 | cout << "ABSENT\n"; 71 | } -------------------------------------------------------------------------------- /codesnippet.cpp: -------------------------------------------------------------------------------- 1 | // Nisarg Gogate 2 | // VNIT 3 | 4 | #include 5 | #define DEBUG_ON 0 6 | #define int long long 7 | #define TESTCASES false 8 | #define FASTIO true 9 | #define DBG(x) if(DEBUG_ON) cout << #x << " == " << x << endl 10 | #define FF first 11 | #define SS second 12 | 13 | const int inf = (int)1e18 + 1; 14 | const int SIZE = (int)1e5+3; 15 | const int MOD = (int)1e9+7; 16 | using namespace std; 17 | 18 | int exp(int x,int n) 19 | { 20 | int ret= 1; 21 | while(n>0) 22 | { 23 | if(n%2)ret=(ret*x)%MOD; 24 | x=(x*x)%MOD; 25 | n=n/2; 26 | } 27 | return ret%MOD; 28 | } 29 | int inv(int x) 30 | { 31 | return exp(x,MOD-2); 32 | } 33 | 34 | int ncr(int n,int r) 35 | { 36 | if(r==0)return 1; 37 | if(n arr(n,0); 49 | for (auto &it : arr) cin >> it; 50 | 51 | } 52 | 53 | void main_code() 54 | { 55 | int i,j,n,k; 56 | cin>>n; 57 | cout<> T; 74 | 75 | while(T--) 76 | main_code(); 77 | 78 | } 79 | --------------------------------------------------------------------------------