From 43c1dac6accd39d48c2478231aa35fa8a5561acf Mon Sep 17 00:00:00 2001 From: Akash Gautam <76935019+geekblower@users.noreply.github.com> Date: Thu, 20 Oct 2022 09:43:38 +0530 Subject: [PATCH 1/4] Array in CPP --- CPP/Array/All pair whose sum is k.cpp | 53 ++++ CPP/Array/Array subset of another array.cpp | 46 +++ CPP/Array/Best time to buy stock.cpp | 20 ++ CPP/Array/Choclate distribution problem.cpp | 18 ++ .../Common element in 3 sorted arrays.cpp | 54 ++++ CPP/Array/Count inversion.cpp | 108 +++++++ CPP/Array/Cyclically rotate by 1.cpp | 15 + CPP/Array/Kadane's algorithms.cpp | 19 ++ CPP/Array/Kth max min.cpp | 10 + CPP/Array/Largest continous sum.cpp | 19 ++ .../Longest consequecutive subsequence.cpp | 60 ++++ CPP/Array/Maximum subarray product.cpp | 160 ++++++++++ ...edian of two sorted arrays (diff size).cpp | 293 ++++++++++++++++++ ...dian of two sorted arrays (equal size).cpp | 177 +++++++++++ CPP/Array/Merge 2 sorted arrays.cpp | 88 ++++++ CPP/Array/Merge intervals.cpp | 78 +++++ .../Min swaps requires to group together.cpp | 44 +++ CPP/Array/Minimize the height.cpp | 24 ++ CPP/Array/Minimum jumps to reach end.cpp | 34 ++ .../Negative element to one side of array.cpp | 28 ++ CPP/Array/Next permutation.cpp | 25 ++ CPP/Array/Rearrange position neg in alter.cpp | 153 +++++++++ CPP/Array/Reverse array.cpp | 36 +++ CPP/Array/Sell buy stock almost twice.cpp | 76 +++++ ...llest subarray with sum greater than k.cpp | 34 ++ CPP/Array/Subarray with sum 0.cpp | 53 ++++ CPP/Array/Three way partitioning array.cpp | 21 ++ CPP/Array/Trap rain water problem.cpp | 26 ++ CPP/Array/Triplet of element sum.cpp | 66 ++++ 29 files changed, 1838 insertions(+) create mode 100644 CPP/Array/All pair whose sum is k.cpp create mode 100644 CPP/Array/Array subset of another array.cpp create mode 100644 CPP/Array/Best time to buy stock.cpp create mode 100644 CPP/Array/Choclate distribution problem.cpp create mode 100644 CPP/Array/Common element in 3 sorted arrays.cpp create mode 100644 CPP/Array/Count inversion.cpp create mode 100644 CPP/Array/Cyclically rotate by 1.cpp create mode 100644 CPP/Array/Kadane's algorithms.cpp create mode 100644 CPP/Array/Kth max min.cpp create mode 100644 CPP/Array/Largest continous sum.cpp create mode 100644 CPP/Array/Longest consequecutive subsequence.cpp create mode 100644 CPP/Array/Maximum subarray product.cpp create mode 100644 CPP/Array/Median of two sorted arrays (diff size).cpp create mode 100644 CPP/Array/Median of two sorted arrays (equal size).cpp create mode 100644 CPP/Array/Merge 2 sorted arrays.cpp create mode 100644 CPP/Array/Merge intervals.cpp create mode 100644 CPP/Array/Min swaps requires to group together.cpp create mode 100644 CPP/Array/Minimize the height.cpp create mode 100644 CPP/Array/Minimum jumps to reach end.cpp create mode 100644 CPP/Array/Negative element to one side of array.cpp create mode 100644 CPP/Array/Next permutation.cpp create mode 100644 CPP/Array/Rearrange position neg in alter.cpp create mode 100644 CPP/Array/Reverse array.cpp create mode 100644 CPP/Array/Sell buy stock almost twice.cpp create mode 100644 CPP/Array/Smallest subarray with sum greater than k.cpp create mode 100644 CPP/Array/Subarray with sum 0.cpp create mode 100644 CPP/Array/Three way partitioning array.cpp create mode 100644 CPP/Array/Trap rain water problem.cpp create mode 100644 CPP/Array/Triplet of element sum.cpp diff --git a/CPP/Array/All pair whose sum is k.cpp b/CPP/Array/All pair whose sum is k.cpp new file mode 100644 index 0000000..ae8aeb1 --- /dev/null +++ b/CPP/Array/All pair whose sum is k.cpp @@ -0,0 +1,53 @@ +/* + link: https://practice.geeksforgeeks.org/problems/count-pairs-with-given-sum5022/1 + + https://www.geeksforgeeks.org/count-pairs-with-given-sum/ +*/ + + +// ----------------------------------------------------------------------------------------------------------------------- // +// using hashing (aka unordered_map) +int getPairsCount(int arr[], int n, int sum) +{ + unordered_map m; + + // Store counts of all elements in map m + for (int i = 0; i < n; i++) + m[arr[i]]++; + + int twice_count = 0; + + // iterate through each element and increment the + // count (Notice that every pair is counted twice) + for (int i = 0; i < n; i++) { + twice_count += m[sum - arr[i]]; + + // if (arr[i], arr[i]) pair satisfies the condition, + // then we need to ensure that the count is + // decreased by one such that the (arr[i], arr[i]) + // pair is not considered + if (sum - arr[i] == arr[i]) + twice_count--; + } + + // return the half of twice_count + return twice_count / 2; +} + + + +// ----------------------------------------------------------------------------------------------------------------------- // +// naive solution (TLE) +// TC: O(n^2) +int getPairsCount(int arr[], int n, int sum) +{ + int count = 0; // Initialize result + + // Consider all possible pairs and check their sums + for (int i = 0; i < n; i++) + for (int j = i + 1; j < n; j++) + if (arr[i] + arr[j] == sum) + count++; + + return count; +} \ No newline at end of file diff --git a/CPP/Array/Array subset of another array.cpp b/CPP/Array/Array subset of another array.cpp new file mode 100644 index 0000000..aa34fc8 --- /dev/null +++ b/CPP/Array/Array subset of another array.cpp @@ -0,0 +1,46 @@ +/* + link: https://practice.geeksforgeeks.org/problems/array-subset-of-another-array2317/1# +*/ + + +// ----------------------------------------------------------------------------------------------------------------------- // +// TC: O(N) +// SC: O(N) +string isSubset(int a1[], int a2[], int n, int m) { + unordered_set s; + for (int i = 0;i < n;i++) { + s.insert(a1[i]); + } + for (int i = 0;i < m;i++) { + if (s.find(a2[i]) == s.end()) return "No"; + } + return "Yes"; +} + + + +// ----------------------------------------------------------------------------------------------------------------------- // +// similar solution. +string isSubset(int a1[], int a2[], int n, int m) { + + unordered_map um, um2; + + for (int i = 0; i < n; i++) { + um[a1[i]]++; + } + for (int i = 0; i < m; i++) { + um2[a2[i]]++; + } + + int count = 0; + for (auto it = um2.begin(); it != um2.end(); it++) { + if (um[it->first] >= it->second) { + count++; + } + } + + if (count == m) + return "Yes"; + else + return "No"; +} \ No newline at end of file diff --git a/CPP/Array/Best time to buy stock.cpp b/CPP/Array/Best time to buy stock.cpp new file mode 100644 index 0000000..1723be1 --- /dev/null +++ b/CPP/Array/Best time to buy stock.cpp @@ -0,0 +1,20 @@ +/* + link: https://leetcode.com/problems/best-time-to-buy-and-sell-stock/ + + also refer to 26_sell_...twice.cpp +*/ + + +// ----------------------------------------------------------------------------------------------------------------------- // +int maxProfit(vector& prices) { + int n = prices.size(); + int local = 0, global = 0; + for (int i = 1;i < n;i++) { + /* + if the loss is going negative then make it 0 either continue with the profit as higher as possible. + */ + local = max(0, local += prices[i] - prices[i - 1]); + global = max(local, global); + } + return global; +} diff --git a/CPP/Array/Choclate distribution problem.cpp b/CPP/Array/Choclate distribution problem.cpp new file mode 100644 index 0000000..d56384a --- /dev/null +++ b/CPP/Array/Choclate distribution problem.cpp @@ -0,0 +1,18 @@ +/* + link: https://practice.geeksforgeeks.org/problems/chocolate-distribution-problem3825/1 +*/ + + +// ----------------------------------------------------------------------------------------------------------------------- // +long long findMinDiff(vector a, long long n, long long m) { + // sorted so that we can different window(sub-array) of size m. + sort(a.begin(), a.end()); + + long long ans = a[m - 1] - a[0]; // took first window from 0 to m-1. + + // now we iterate every window(sub-array) and check for the max-min from that range. + for (int i = 1;i < n - m + 1;i++) { + ans = min(a[i + m - 1] - a[i], ans); + } + return ans; +} \ No newline at end of file diff --git a/CPP/Array/Common element in 3 sorted arrays.cpp b/CPP/Array/Common element in 3 sorted arrays.cpp new file mode 100644 index 0000000..61829ca --- /dev/null +++ b/CPP/Array/Common element in 3 sorted arrays.cpp @@ -0,0 +1,54 @@ +/* + link: https://practice.geeksforgeeks.org/problems/common-elements1132/1 +*/ + + +// ----------------------------------------------------------------------------------------------------------------------- // +vector commonElements(int a[], int b[], int c[], int n1, int n2, int n3) +{ + set ans; + int i = 0, j = 0, k = 0; + while (i < n1 and j < n2 and k < n3) { + if (a[i] == b[j] && a[i] == c[k]) { + ans.insert(a[i]); + i++; + j++; + k++; + } + else if (a[i] < b[j] || a[i] < c[k]) i++; + else if (b[j] < a[i] || b[j] < c[k]) j++; + else if (c[k] < b[j] || c[k] < a[i]) k++; + } + vector nn; + for (ele : ans) { + nn.push_back(ele); + } + return nn; +} + + + +// ----------------------------------------------------------------------------------------------------------------------- // +// alternate solution (improved) +vector commonElements(int A[], int B[], int C[], int n1, int n2, int n3) +{ + int i = 0, j = 0, k = 0; + + vector res; + int last = INT_MIN; + while (i < n1 and j < n2 and k < n3) + { + if (A[i] == B[j] and A[i] == C[k] and A[i] != last) + { + res.push_back(A[i]); + last = A[i]; + i++; + j++; + k++; + } + else if (min({ A[i], B[j], C[k] }) == A[i]) i++; + else if (min({ A[i], B[j], C[k] }) == B[j]) j++; + else k++; + } + return res; +} \ No newline at end of file diff --git a/CPP/Array/Count inversion.cpp b/CPP/Array/Count inversion.cpp new file mode 100644 index 0000000..d56ff1b --- /dev/null +++ b/CPP/Array/Count inversion.cpp @@ -0,0 +1,108 @@ +/* + link: https://practice.geeksforgeeks.org/problems/inversion-of-array-1587115620/1# + + video (recommended to save time): https://youtu.be/kQ1mJlwW-c0 + + condition here is convertion counts if (arr[i]>arr[j] && i left) { + /* Divide the array into two parts and call _mergeSortAndCountInv() for each of the parts */ + mid = (right + left) / 2; + + /* Inversion count will be sum of inversions in left-part, right-part and number of inversions in merging */ + inv_count += _mergeSort(arr, temp, left, mid); + inv_count += _mergeSort(arr, temp, mid + 1, right); + + /*Merge the two parts*/ + inv_count += merge(arr, temp, left, mid + 1, right); + } + return inv_count; +} + +// Driver code +int main() +{ + int arr[] = { 1, 20, 6, 4, 5 }; + int n = sizeof(arr) / sizeof(arr[0]); + int temp[n]; + int ans = _mergeSort(arr, temp, 0, n - 1); + cout << " Number of inversions are " << ans; + return 0; +} diff --git a/CPP/Array/Cyclically rotate by 1.cpp b/CPP/Array/Cyclically rotate by 1.cpp new file mode 100644 index 0000000..667ee0e --- /dev/null +++ b/CPP/Array/Cyclically rotate by 1.cpp @@ -0,0 +1,15 @@ +/* + link: https://practice.geeksforgeeks.org/problems/cyclically-rotate-an-array-by-one2614/1 +*/ + + +// ----------------------------------------------------------------------------------------------------------------------- // +void rotate(int arr[], int n) +{ + int temp = arr[n - 1]; + + for (int i = n - 1;i > 0;i--) { + arr[i] = arr[i - 1]; + } + arr[0] = temp; +} \ No newline at end of file diff --git a/CPP/Array/Kadane's algorithms.cpp b/CPP/Array/Kadane's algorithms.cpp new file mode 100644 index 0000000..9d4a1b6 --- /dev/null +++ b/CPP/Array/Kadane's algorithms.cpp @@ -0,0 +1,19 @@ +/* + link: https://practice.geeksforgeeks.org/problems/kadanes-algorithm-1587115620/1 +*/ + + +// ----------------------------------------------------------------------------------------------------------------------- // +int maxSubarraySum(int arr[], int n) { + int dp[n]; + dp[0] = max(INT_MIN, arr[0]); + int omax = dp[0]; + + for (int i = 1;i < n;i++) { + + dp[i] = max(arr[i] + dp[i - 1], arr[i]); + + omax = max(dp[i], omax); + } + return omax; +} \ No newline at end of file diff --git a/CPP/Array/Kth max min.cpp b/CPP/Array/Kth max min.cpp new file mode 100644 index 0000000..5ca540e --- /dev/null +++ b/CPP/Array/Kth max min.cpp @@ -0,0 +1,10 @@ +/* + link: https://practice.geeksforgeeks.org/problems/kth-smallest-element5635/1 + + sol: https://www.geeksforgeeks.org/kth-smallestlargest-element-unsorted-array/ + or + refer heap/5th_kth....cpp + +*/ + + diff --git a/CPP/Array/Largest continous sum.cpp b/CPP/Array/Largest continous sum.cpp new file mode 100644 index 0000000..48f3b90 --- /dev/null +++ b/CPP/Array/Largest continous sum.cpp @@ -0,0 +1,19 @@ +/* + link: https://practice.geeksforgeeks.org/problems/kadanes-algorithm-1587115620/1 + + kadane's algorithm +*/ + + +// ----------------------------------------------------------------------------------------------------------------------- // +int maxSubarraySum(int arr[], int n) { + int dp[n]; + + dp[0] = max(0, arr[0]); + int omax = dp[0]; + for (int i = 1;i < n;i++) { + dp[i] = max(dp[i - 1] + arr[i], arr[i]); + omax = max(dp[i], omax); + } + return omax; +} \ No newline at end of file diff --git a/CPP/Array/Longest consequecutive subsequence.cpp b/CPP/Array/Longest consequecutive subsequence.cpp new file mode 100644 index 0000000..8c3dc2b --- /dev/null +++ b/CPP/Array/Longest consequecutive subsequence.cpp @@ -0,0 +1,60 @@ +/* + link: https://practice.geeksforgeeks.org/problems/longest-consecutive-subsequence2449/1 +*/ + + +// ----------------------------------------------------------------------------------------------------------------------- // +int findLongestConseqSubseq(int arr[], int N) +{ + //Your code here + int range = 1e6; + int cnt[range]; + memset(cnt, 0, sizeof(cnt)); + for (int i = 0;i < N;i++) { + cnt[arr[i]]++; + } + int local = 0, global = 0; + for (int i = 0;i < range;i++) { + if (cnt[i] > 0) local++; + else local = 0; + global = max(global, local); + } + return global; +} + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +// using hashing +int findLongestConseqSubseq(int arr[], int n) +{ + //using a Set to store elements. + unordered_set S; + int ans = 0; + + //inserting all the array elements in Set. + for (int i = 0; i < n; i++) + S.insert(arr[i]); + + //checking each possible sequence from the start. + for (int i = 0; i < n; i++) + { + //if current element is starting element of a sequence then only + //we try to find out the length of sequence. + if (S.find(arr[i] - 1) == S.end()) + { + + int j = arr[i]; + //then we keep checking whether the next consecutive elements + //are present in Set and we keep incrementing the counter. + while (S.find(j) != S.end()) + j++; + + //storing the maximum count. + ans = max(ans, j - arr[i]); + } + } + //returning the length of longest subsequence + return ans; +} \ No newline at end of file diff --git a/CPP/Array/Maximum subarray product.cpp b/CPP/Array/Maximum subarray product.cpp new file mode 100644 index 0000000..f0d8a63 --- /dev/null +++ b/CPP/Array/Maximum subarray product.cpp @@ -0,0 +1,160 @@ +/* + link: https://practice.geeksforgeeks.org/problems/maximum-product-subarray3604/1 + + sol: https://www.geeksforgeeks.org/maximum-product-subarray/ +*/ + + + +// ----------------------------------------------------------------------------------------------------------------------- // +// easiest solution +long long maxProduct(int* arr, int n) { + // Variables to store maximum and minimum + // product till ith index. + long long minVal = arr[0]; + long long maxVal = arr[0]; + + long long maxProduct = arr[0]; + + for (int i = 1; i < n; i++) { + + // When multiplied by -ve number, + // maxVal becomes minVal + // and minVal becomes maxVal. + if (arr[i] < 0) swap(maxVal, minVal); + + // maxVal and minVal stores the + // product of subarray ending at arr[i]. + maxVal = max((long long)arr[i], maxVal * arr[i]); + minVal = min((long long)arr[i], minVal * arr[i]); + + // Max Product of array. + maxProduct = max(maxProduct, maxVal); + } + + // Return maximum product found in array. + return maxProduct; +} + + + +// ----------------------------------------------------------------------------------------------------------------------- // +// TC: O(N) +// SC: O(1) +int maxSubarrayProduct(int arr[], int n) +{ + // max positive product + // ending at the current position + int max_ending_here = 1; + + // min negative product ending + // at the current position + int min_ending_here = 1; + + // Initialize overall max product + int max_so_far = 0; + int flag = 0; + /* Traverse through the array. + Following values are + maintained after the i'th iteration: + max_ending_here is always 1 or + some positive product ending with arr[i] + min_ending_here is always 1 or + some negative product ending with arr[i] */ + for (int i = 0; i < n; i++) + { + /* If this element is positive, update + max_ending_here. Update min_ending_here only if + min_ending_here is negative */ + if (arr[i] > 0) + { + max_ending_here = max_ending_here * arr[i]; + min_ending_here + = min(min_ending_here * arr[i], 1); + flag = 1; + } + + /* If this element is 0, then the maximum product + cannot end here, make both max_ending_here and + min_ending_here 0 + Assumption: Output is alway greater than or equal + to 1. */ + else if (arr[i] == 0) { + max_ending_here = 1; + min_ending_here = 1; + } + + /* If element is negative. This is tricky + max_ending_here can either be 1 or positive. + min_ending_here can either be 1 or negative. + next max_ending_here will always be prev. + min_ending_here * arr[i] ,next min_ending_here + will be 1 if prev max_ending_here is 1, otherwise + next min_ending_here will be prev max_ending_here * + arr[i] */ + + else { + int temp = max_ending_here; + max_ending_here = max(min_ending_here * arr[i], 1); + min_ending_here = temp * arr[i]; + } + + // update max_so_far, if needed + if (max_so_far < max_ending_here) + max_so_far = max_ending_here; + } + if (flag == 0 && max_so_far == 0) + return 0; + return max_so_far; +} + + + +// ----------------------------------------------------------------------------------------------------------------------- // +// similar solution +long long maxProduct(int* arr, int n) { + long long l_min = 1, l_max = 1, global = 0; + for (int i = 0;i < n;i++) { + if (arr[i] == 0) { + l_min = 1; + l_max = 1; + } + else if (arr[i] > 0) { + l_max *= arr[i]; + l_min = min(l_min * arr[i], 1LL); + } + else { + long long copy_l_max = l_max; + l_max = max(l_min * arr[i], 1LL); + l_min = min(copy_l_max * arr[i], 1LL); + } + global = max(global, l_max); + } + return global; +} + + + +// ----------------------------------------------------------------------------------------------------------------------- // +// naive solution +int maxSubarrayProduct(int arr[], int n) +{ + // Initializing result + int result = arr[0]; + + for (int i = 0; i < n; i++) + { + int mul = arr[i]; + // traversing in current subarray + for (int j = i + 1; j < n; j++) + { + // updating result every time + // to keep an eye over the maximum product + result = max(result, mul); + mul *= arr[j]; + } + // updating the result for (n-1)th index. + result = max(result, mul); + } + return result; +} \ No newline at end of file diff --git a/CPP/Array/Median of two sorted arrays (diff size).cpp b/CPP/Array/Median of two sorted arrays (diff size).cpp new file mode 100644 index 0000000..da79e7a --- /dev/null +++ b/CPP/Array/Median of two sorted arrays (diff size).cpp @@ -0,0 +1,293 @@ +/* + link: https://www.geeksforgeeks.org/median-of-two-sorted-arrays-of-different-sizes/ +*/ + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + A Simple Merge based solution to find median of two sorted arrays + + Time Complexity: O(m + n). +*/ +int getMedian(int ar1[], int ar2[], int n, int m) +{ + int i = 0; /* Current index of input array ar1[] */ + int j = 0; /* Current index of input array ar2[] */ + int count; + int m1 = -1, m2 = -1; + + // Since there are (n+m) elements, + // There are following two cases + // if n+m is odd then the middle + //index is median i.e. (m+n)/2 + if ((m + n) % 2 == 1) + { + for (count = 0; count <= (n + m) / 2; count++) + { + if (i != n && j != m) + { + m1 = (ar1[i] > ar2[j]) ? ar2[j++] : ar1[i++]; + } + else if (i < n) + { + m1 = ar1[i++]; + } + // for case when j ar2[j]) ? ar2[j++] : ar1[i++]; + } + else if (i < n) + { + m1 = ar1[i++]; + } + // for case when j B[idxB], then median must exist in + A[...idxA] and B[idxB....] */ + return findMedianUtil(A, N / 2 + 1, B + idxA, M - idxA); +} + +// A wrapper function around findMedianUtil(). This function +// makes sure that smaller array is passed as first argument +// to findMedianUtil +float findMedian(int A[], int N, int B[], int M) +{ + if (N > M) + return findMedianUtil(B, M, A, N); + + return findMedianUtil(A, N, B, M); +} + +// Driver program to test above functions +int main() +{ + int A[] = { 900 }; + int B[] = { 5, 8, 10, 20 }; + + int N = sizeof(A) / sizeof(A[0]); + int M = sizeof(B) / sizeof(B[0]); + + printf("%f", findMedian(A, N, B, M)); + return 0; +} + + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + simple but costly solution + + Time Complexity: O(n Log n) + Space Complexity: O(i+j) +*/ +// C++ program for the above approach +#include +using namespace std; + +int Solution(int arr[], int n) +{ + + // If length of array is even + if (n % 2 == 0) + { + int z = n / 2; + int e = arr[z]; + int q = arr[z - 1]; + int ans = (e + q) / 2; + return ans; + } + + // If length if array is odd + else + { + int z = round(n / 2); + return arr[z]; + } +} + +// Driver Code +int main() { + + // TODO Auto-generated method stub + int arr1[] = { -5, 3, 6, 12, 15 }; + int arr2[] = { -12, -10, -6, -3, 4, 10 }; + + int i = sizeof(arr1) / sizeof(arr1[0]); + int j = sizeof(arr2) / sizeof(arr2[0]); + + int arr3[i + j]; + int l = i + j; + // Merge two array into one array + for (int k = 0;k < i;k++) + { + arr3[k] = arr1[k]; + } + + for (int k = i;k < l;k++) + { + arr3[k] = arr2[k]; + } + + // Sort the merged array + sort(arr3, arr3 + l); + + // calling the method + cout << "Median = " << Solution(arr3, l); +} diff --git a/CPP/Array/Median of two sorted arrays (equal size).cpp b/CPP/Array/Median of two sorted arrays (equal size).cpp new file mode 100644 index 0000000..53c5567 --- /dev/null +++ b/CPP/Array/Median of two sorted arrays (equal size).cpp @@ -0,0 +1,177 @@ +/* + link: https://www.geeksforgeeks.org/median-of-two-sorted-arrays/ +*/ + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + by counting until the count reach n-1 and n. which would have been the median pos in sorted merged array + Time Complexity : O(n) +*/ +int getMedian(int ar1[], + int ar2[], int n) +{ + int i = 0; /* Current index of i/p array ar1[] */ + int j = 0; /* Current index of i/p array ar2[] */ + int count; + int m1 = -1, m2 = -1; + + /* Since there are 2n elements, median will be average of elements + at index n-1 and n in the array obtained after merging ar1 and ar2 */ + for (count = 0; count <= n; count++) + { + /* Below is to handle case where all elements of ar1[] are smaller than smallest(or first) + element of ar2[]*/ + if (i == n) + { + m1 = m2; + m2 = ar2[0]; + break; + } + /*Below is to handle case where all elements of ar2[] are + smaller than smallest(or first) element of ar1[]*/ + else if (j == n) + { + m1 = m2; + m2 = ar1[0]; + break; + } + /* equals sign because if two arrays have some common elements */ + if (ar1[i] <= ar2[j]) + { + /* Store the prev median */ + m1 = m2; + m2 = ar1[i]; + i++; + } + else + { + /* Store the prev median */ + m1 = m2; + m2 = ar2[j]; + j++; + } + } + return (m1 + m2) / 2; +} + +// Driver Code +int main() +{ + int ar1[] = { 1, 12, 15, 26, 38 }; + int ar2[] = { 2, 13, 17, 30, 45 }; + + int n1 = sizeof(ar1) / sizeof(ar1[0]); + int n2 = sizeof(ar2) / sizeof(ar2[0]); + if (n1 == n2) cout << "Median is " << getMedian(ar1, ar2, n1); + else cout << "Doesn't work for arrays" << " of unequal size"; + getchar(); + return 0; +} + + + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + By comparing the medians of two arrays (divide and conquer approach) + + main logic is lets say 1st array's median is smaller than 2nd's, it proves that 1st array has more smaller + element compare to 2nd array hence we shifted accordingly + + Time Complexity : O(logn) +*/ + +/* Function to get median of a sorted array */ +int median(int arr[], int n) +{ + if (n % 2 == 0) return (arr[n / 2] + arr[n / 2 - 1]) / 2; + else return arr[n / 2]; +} +int getMedian(int ar1[], + int ar2[], int n) +{ + /* return -1 for invalid input */ + if (n <= 0) return -1; + if (n == 1) return (ar1[0] + ar2[0]) / 2; + if (n == 2) return (max(ar1[0], ar2[0]) + min(ar1[1], ar2[1])) / 2; + +/* get the median of the first array */ + int m1 = median(ar1, n); + + /* get the median of the second array */ + int m2 = median(ar2, n); + + /* If medians are equal then return either m1 or m2 */ + if (m1 == m2) return m1; // as (m1 + m1)/2 == m1 + + /* if m1 < m2 then median must exist in ar1[m1....] and ar2[....m2] */ + if (m1 < m2) + { + // as we are passing address of ar1[0] hence we can pass desired pos by adding integer. + if (n % 2 == 0) return getMedian(ar1 + n / 2 - 1, ar2, n - (n / 2 - 1)); + return getMedian(ar1 + n / 2, ar2, n - n / 2); + } + + /* if m1 > m2 then median must exist in ar1[....m1] and ar2[m2...] */ + if (n % 2 == 0) return getMedian(ar2 + n / 2 - 1, ar1, n - (n / 2 - 1)); + return getMedian(ar2 + n / 2, ar1, n - n / 2); +} +// Driver code +int main() +{ + int ar1[] = { 1, 2, 3, 6 }; + int ar2[] = { 4, 6, 8, 10 }; + int n1 = sizeof(ar1) / + sizeof(ar1[0]); + int n2 = sizeof(ar2) / + sizeof(ar2[0]); + if (n1 == n2) + cout << "Median is " << getMedian(ar1, ar2, n1); + else + cout << "Doesn't work for arrays " << "of unequal size"; + return 0; +} + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + By taking union w/o extra space + + Time Complexity : O(nlogn) +*/ + +int getMedian(int ar1[], int ar2[], int n) +{ + int j = 0; + int i = n - 1; + while (ar1[i] > ar2[j] && j < n && i > -1) + swap(ar1[i--], ar2[j++]); + sort(ar1, ar1 + n); + sort(ar2, ar2 + n); + + // as both array are sorted (imagine both are continuous) + return (ar1[n - 1] + ar2[0]) / 2; +} + +// Driver Code +int main() +{ + int ar1[] = { 1, 12, 15, 26, 38 }; + int ar2[] = { 2, 13, 17, 30, 45 }; + + int n1 = sizeof(ar1) / sizeof(ar1[0]); + int n2 = sizeof(ar2) / sizeof(ar2[0]); + if (n1 == n2) + cout << "Median is " << getMedian(ar1, ar2, n1); + else + cout << "Doesn't work for arrays" + << " of unequal size"; + getchar(); + return 0; +} \ No newline at end of file diff --git a/CPP/Array/Merge 2 sorted arrays.cpp b/CPP/Array/Merge 2 sorted arrays.cpp new file mode 100644 index 0000000..4cd4cf6 --- /dev/null +++ b/CPP/Array/Merge 2 sorted arrays.cpp @@ -0,0 +1,88 @@ +/* + link: https://practice.geeksforgeeks.org/problems/merge-two-sorted-arrays5135/1 + + sol: https://www.geeksforgeeks.org/merge-two-sorted-arrays-o1-extra-space/ +*/ + + + +// ----------------------------------------------------------------------------------------------------------------------- // +// correct solution +void merge(int arr1[], int arr2[], int n, int m) +{ + int i = 0, j = 0, k = n - 1; + + // Untill i less than equal to k + // or j is less tha m + while (i <= k and j < m) { + if (arr1[i] < arr2[j]) + i++; + else { + swap(arr2[j++], arr1[k--]); + } + } + // swap with the largest element. + + // Sort first array + sort(arr1, arr1 + n); + + // Sort second array + sort(arr2, arr2 + m); +} + + + +// ----------------------------------------------------------------------------------------------------------------------- // +// tc: O(m*n) so TLE. +// but this code will keep both the array sorted throughout +void merge(int ar1[], int ar2[], int n, int m) +{ + // Iterate through all elements + // of ar2[] starting from the last element + for (int j = m - 1; j >= 0; j--) + { + /* Find the smallest element greater than ar2[j]. + Move all elements one position ahead till the + smallest greater element is not found */ + int i, last = ar1[n - 1]; + + // here array will be making space for the new element to insert + for (i = n - 2; i >= 0 && ar1[i] > ar2[j]; i--) + ar1[i + 1] = ar1[i]; + + // If there was a greater element + if (i != n - 2 || last > ar2[j]) + { + ar1[i + 1] = ar2[j]; + ar2[j] = last; + } + } +} + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* using extra space (this code wont work although its correct bcoz gfg will only +analyze their arr1and arr2 as we cant use extra space) */ +void merge(int arr1[], int arr2[], int n, int m) { + // code here + vector arr; + int i = 0, j = 0; + + while (i < n && j < m) { + if (arr1[i] == arr2[j]) { + arr.push_back(arr1[i++]); + arr.push_back(arr2[j++]); + } + else if (arr1[i] < arr2[j]) arr.push_back(arr1[i++]); + else arr.push_back(arr2[j++]); + } + while (i < n) arr.push_back(arr1[i++]); + + while (j < m) arr.push_back(arr2[j++]); + + for (int i = 0;i < arr.size();i++) { + cout << arr[i] << " "; + } +} \ No newline at end of file diff --git a/CPP/Array/Merge intervals.cpp b/CPP/Array/Merge intervals.cpp new file mode 100644 index 0000000..7201682 --- /dev/null +++ b/CPP/Array/Merge intervals.cpp @@ -0,0 +1,78 @@ +/* + link: https://leetcode.com/problems/merge-intervals/ + + simple greedy approach +*/ + +// ----------------------------------------------------------------------------------------------------------------------- // +vector> merge(vector>& intervals) { + int n = intervals.size(); + int idx = 0; + for (int i = 1;i < n;i++) { + long long& idx_end = intervals[idx].second; + if (idx_end >= intervals[i].first) { + idx_end = max(idx_end, intervals[i].first); + } + else { + idx++; + intervals[idx] = intervals[i]; + } + } + + vector> ans(intervals.begin(), intervals.begin() + idx + 1); + return ans; +} + + +// ----------------------------------------------------------------------------------------------------------------------- // +vector> merge(vector>& intervals) { + vector> ans; + int k = 0; + sort(intervals.begin(), intervals.end()); + + int start = intervals[0][0], end = intervals[0][1]; + for (int i = 1;i < intervals.size();i++) { + if (intervals[i][0] <= end) { + end = max(end, intervals[i][1]); + } + else { + ans.push_back({ start, end }); + start = intervals[i][0]; + end = intervals[i][1]; + } + } + if (!ans.size() || ans[ans.size() - 1][1] != intervals[intervals.size() - 1][1]) ans.push_back({ start, end }); + return ans; +} + + + +// ----------------------------------------------------------------------------------------------------------------------- // +vector> merge(vector>& intervals) { + if (!intervals.size()) return {}; + + sort(intervals.begin(), intervals.end()); + + int right = 1; + int lval = intervals[0][0]; + int rval = intervals[0][1]; + int n = intervals.size(); + vector> ans; + + while (right < n) { + if (rval > intervals[right][1]) right++; + else if (rval < intervals[right][0]) { + ans.push_back({ lval,rval }); + lval = intervals[right][0]; + rval = intervals[right][1]; + right++; + } + else if (rval >= intervals[right][0] && rval <= intervals[right][1]) { + rval = intervals[right][1]; + right++; + } + + } + ans.push_back({ lval,rval }); + return ans; +} \ No newline at end of file diff --git a/CPP/Array/Min swaps requires to group together.cpp b/CPP/Array/Min swaps requires to group together.cpp new file mode 100644 index 0000000..3177c37 --- /dev/null +++ b/CPP/Array/Min swaps requires to group together.cpp @@ -0,0 +1,44 @@ +/* + link: https://practice.geeksforgeeks.org/problems/minimum-swaps-required-to-bring-all-elements-less-than-or-equal-to-k-together4847/1# + + sol: https://www.geeksforgeeks.org/minimum-swaps-required-bring-elements-less-equal-k-together/ +*/ + + + +// ----------------------------------------------------------------------------------------------------------------------- // +int minSwap(int* arr, int n, int k) { + + // Find count of elements which are + // less than equals to k + int count = 0; + for (int i = 0; i < n; ++i) + if (arr[i] <= k) + ++count; + + // Find unwanted elements in current + // window of size 'count' + int bad = 0; + for (int i = 0; i < count; ++i) + if (arr[i] > k) + ++bad; + + // Initialize answer with 'bad' value of + // current window + int ans = bad; + for (int i = 0, j = count; j < n; ++i, ++j) { + + // Decrement count of previous window + if (arr[i] > k) + --bad; + + // Increment count of current window + if (arr[j] > k) + ++bad; + + // Update ans if count of 'bad' + // is less in current window + ans = min(ans, bad); + } + return ans; +} diff --git a/CPP/Array/Minimize the height.cpp b/CPP/Array/Minimize the height.cpp new file mode 100644 index 0000000..ba3169f --- /dev/null +++ b/CPP/Array/Minimize the height.cpp @@ -0,0 +1,24 @@ +/* + link: https://practice.geeksforgeeks.org/problems/minimize-the-heights3351/1# + + sol: https://www.geeksforgeeks.org/minimize-the-maximum-difference-between-the-heights/ + note: this above sol. by geeks for geeks is not working... :( +*/ + + +// ----------------------------------------------------------------------------------------------------------------------- // +// simple and correct solution. +int getMinDiff(int arr[], int n, int k) { + if (n == 1) return 0; + sort(arr, arr + n); + int ans = arr[n - 1] - arr[0]; + + for (int i = 0;i < n;i++) { + if (arr[i] < k) continue; // to avoid negative height in curr_min + int curr_min = min(arr[0] + k, arr[i] - k); + int curr_max = max(arr[n - 1] - k, arr[i - 1] + k); + if (curr_max < curr_min) continue; // as max till now can't be smaller than min till now hence ignore that element. + ans = min(ans, curr_max - curr_min); + } + return ans; +} diff --git a/CPP/Array/Minimum jumps to reach end.cpp b/CPP/Array/Minimum jumps to reach end.cpp new file mode 100644 index 0000000..f6fe149 --- /dev/null +++ b/CPP/Array/Minimum jumps to reach end.cpp @@ -0,0 +1,34 @@ +/* + link: https://practice.geeksforgeeks.org/problems/minimum-number-of-jumps-1587115620/1# +*/ + + +// ----------------------------------------------------------------------------------------------------------------------- // +int minJumps(int arr[], int n) { + + // base condition + if (n <= 1) return 0; + if (arr[0] == 0) return -1; + + int maxReach = arr[0]; + int step = arr[0]; + int jump = 1; + + for (int i = 1;i < n;i++) { + if (i == n - 1) return jump; + + maxReach = max(maxReach, arr[i] + i); + + step--; // do step-- until its 0 as we r sure we can reach till that end but parallely keep updating maxReach + + if (step == 0) { + jump++; + + if (i >= maxReach) return -1; + + step = maxReach - i; // here we got help of that maxReach + // this shows that why iterating all the elements till now how max. farthest we can go and we will set step as such. + } + } + return -1; +} \ No newline at end of file diff --git a/CPP/Array/Negative element to one side of array.cpp b/CPP/Array/Negative element to one side of array.cpp new file mode 100644 index 0000000..1e2a8c9 --- /dev/null +++ b/CPP/Array/Negative element to one side of array.cpp @@ -0,0 +1,28 @@ +/* + link: https://www.geeksforgeeks.org/move-negative-numbers-beginning-positive-end-constant-extra-space/ + + variation: 2-pointer +*/ + + +// ----------------------------------------------------------------------------------------------------------------------- // +void arrange(int a[], int n) { + int negi = 0; + int posi = n - 1; + + while (negi <= posi) { + if (a[negi] < 0 && a[posi] < 0) { + negi++; + } + else if (a[negi] > 0 && a[posi] < 0) { + swap(a[negi], a[pos]); + negi++; + pos--; + } + else if (a[negi] > 0 && a[posi] > 0) posi--; + else { + negi++; + posi--; + } + } +} \ No newline at end of file diff --git a/CPP/Array/Next permutation.cpp b/CPP/Array/Next permutation.cpp new file mode 100644 index 0000000..dd39628 --- /dev/null +++ b/CPP/Array/Next permutation.cpp @@ -0,0 +1,25 @@ +/* + link: https://leetcode.com/problems/next-permutation/ + + video: https://www.youtube.com/watch?v=LuLCLgMElus +*/ + + +// ----------------------------------------------------------------------------------------------------------------------- // +void nextPermutation(vector& nums) { + int siz = nums.size(); + int i = siz - 2; + + // find point where after which whole sub-array is descending. + while (i >= 0 && nums[i] >= nums[i + 1]) i--; + // so now as rest of the sub array is descending we have to increase the current index. + if (i >= 0) { + int j = siz - 1; + + // find the larger element from the end to swap with. + while (nums[j] <= nums[i]) j--; + swap(nums[j], nums[i]); + } + + reverse(nums.begin() + i + 1, nums.end()); +} diff --git a/CPP/Array/Rearrange position neg in alter.cpp b/CPP/Array/Rearrange position neg in alter.cpp new file mode 100644 index 0000000..018e89c --- /dev/null +++ b/CPP/Array/Rearrange position neg in alter.cpp @@ -0,0 +1,153 @@ +/* + link: https://www.geeksforgeeks.org/rearrange-array-alternating-positive-negative-items-o1-extra-space/ +*/ + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + Time Complexity : O(N^2) + Space Complexity : O(1) +*/ +// Utility function to right rotate all elements between [outofplace, cur] +void rightrotate(int arr[], int n, int outofplace, int cur) +{ + char tmp = arr[cur]; + for (int i = cur; i > outofplace; i--) + arr[i] = arr[i - 1]; + arr[outofplace] = tmp; +} + +void rearrange(int arr[], int n) +{ + int outofplace = -1; + + for (int index = 0; index < n; index++) + { + if (outofplace >= 0) + { + // find the item which must be moved into the out-of-place entry if out-of-place entry is + // positive and current entry is negative OR if out-of-place entry is negative and current + // entry is negative then right rotate + + // [...-3, -4, -5, 6...] --> [...6, -3, -4, -5...] + // ^ ^ + // | | + // outofplace --> outofplace + + if (((arr[index] >= 0) && (arr[outofplace] < 0)) || ((arr[index] < 0) && (arr[outofplace] >= 0))) + { + rightrotate(arr, n, outofplace, index); + + // the new out-of-place entry is now 2 steps ahead + if (index - outofplace >= 2) outofplace = outofplace + 2; + else outofplace = -1; + } + } + + // if no entry has been flagged out-of-place + if (outofplace == -1) { + // check if current entry is out-of-place + if (((arr[index] >= 0) && (!(index % 2))) || ((arr[index] < 0) && (index % 2))) { + outofplace = index; + } + } + } +} + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + JAVA code + + + Time Complexity: O(N*logN) + Space Complexity: O(1) +*/ +public class Main { + + // function which works in the condition when number of + // negative numbers are lesser or equal than positive numbers + static void fill1(int a[], int neg, int pos) + { + if (neg % 2 == 1) { + for (int i = 1; i < neg; i += 2) { + int c = a[i]; + int d = a[i + neg]; + int temp = c; + a[i] = d; + a[i + neg] = temp; + } + } + else { + for (int i = 1; i <= neg; i += 2) { + int c = a[i]; + int d = a[i + neg - 1]; + int temp = c; + a[i] = d; + a[i + neg - 1] = temp; + } + } + } + // function which works in the condition when number of + // negative numbers are greater than positive numbers + static void fill2(int a[], int neg, int pos) + { + if (pos % 2 == 1) { + for (int i = 1; i < pos; i += 2) { + int c = a[i]; + int d = a[i + pos]; + int temp = c; + a[i] = d; + a[i + pos] = temp; + } + } + else { + for (int i = 1; i <= pos; i += 2) { + int c = a[i]; + int d = a[i + pos - 1]; + int temp = c; + a[i] = d; + a[i + pos - 1] = temp; + } + } + } + static void reverse(int a[], int n) + { + int i, k, t; + for (i = 0; i < n / 2; i++) { + t = a[i]; + a[i] = a[n - i - 1]; + a[n - i - 1] = t; + } + } + + public static void main(String[] args) + throws java.lang.Exception + { + // Given array + int[] arr = { -5, -2, 5, 2, 4, 7, 1, 8, 0, -8 }; + int n = arr.length; + + int neg = 0, pos = 0; + for (int i = 0; i < n; i++) { + if (arr[i] < 0) + neg++; + else + pos++; + } + // Sort the array + Arrays.sort(arr); + + if (neg <= pos) { + fill1(arr, neg, pos); + } + else { + // reverse the array in this condition + reverse(arr, n); + fill2(arr, neg, pos); + } + } +} diff --git a/CPP/Array/Reverse array.cpp b/CPP/Array/Reverse array.cpp new file mode 100644 index 0000000..d25ee4e --- /dev/null +++ b/CPP/Array/Reverse array.cpp @@ -0,0 +1,36 @@ +/* + link: https://www.geeksforgeeks.org/write-a-program-to-reverse-an-array-or-string/ + + note: array is pass by reference so no need to worry while changing value it will change in original array. +*/ + + +// ----------------------------------------------------------------------------------------------------------------------- // +// TC: O(N) +void rvereseArray(int arr[], int start, int end) +{ + while (start < end) + { + int temp = arr[start]; + arr[start] = arr[end]; + arr[end] = temp; + start++; + end--; + } +} + + +// ----------------------------------------------------------------------------------------------------------------------- // +// TC: O(N) +void rvereseArray(int arr[], int start, int end) +{ + if (start >= end) + return; + + int temp = arr[start]; + arr[start] = arr[end]; + arr[end] = temp; + + // Recursive Function calling + rvereseArray(arr, start + 1, end - 1); +} \ No newline at end of file diff --git a/CPP/Array/Sell buy stock almost twice.cpp b/CPP/Array/Sell buy stock almost twice.cpp new file mode 100644 index 0000000..506f34a --- /dev/null +++ b/CPP/Array/Sell buy stock almost twice.cpp @@ -0,0 +1,76 @@ +/* + link: https://www.geeksforgeeks.org/maximum-profit-by-buying-and-selling-a-share-at-most-twice/ +*/ + + + +// ----------------------------------------------------------------------------------------------------------------------- // +// very simple and nice solution (for any no. of buy and sell); +// here main logic is we dont care about when to sell or buy just track the profit and acc. it has sold in between. +int main() +{ + int price[] = { 2, 30, 15, 10, 8, 25, 80 }; + int n = 7; + + // adding array + int profit = 0; + + // Initializing variable + // valley-peak approach + for (int i = 1; i < n; i++) + { + // traversing through array from (i+1)th + // position + int sub = price[i] - price[i - 1]; + if (sub > 0) + profit += sub; + } + cout << "Maximum Profit=" << profit; + return 0; +} + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +// just for almost twice +int maxProfit(int price[], int n) +{ + // Create profit array and + // initialize it as 0 + int* profit = new int[n]; + for (int i = 0; i < n; i++) + profit[i] = 0; + + /* Get the maximum profit with only one transaction allowed. After this loop, profit[i] contains maximum + profit from price[i..n-1] using at most one trans. */ + int max_price = price[n - 1]; + for (int i = n - 2; i >= 0; i--) { + // max_price has maximum + // of price[i..n-1] + if (price[i] > max_price) max_price = price[i]; + + // we can get profit[i] by taking maximum of: + // a) previous maximum, i.e., profit[i+1] + // b) profit by buying at price[i] and selling at max_price + profit[i] = max(profit[i + 1], max_price - price[i]); + } + + // here profit[0] will be having max profit by 1 transaction + + /* Get the maximum profit with two transactions allowed After this loop, profit[n-1] contains the result */ + int min_price = price[0]; + for (int i = 1; i < n; i++) { + // min_price is minimum price in price[0..i] + if (price[i] < min_price) min_price = price[i]; + + // Maximum profit is maximum of: + // a) previous maximum, i.e., profit[i-1] + // b) (Buy, Sell) at (min_price, price[i]) and add profit of other trans. stored in profit[i] + profit[i] = max(profit[i - 1], profit[i] + (price[i] - min_price)); + } + int result = profit[n - 1]; + + delete[] profit; // To avoid memory leak + return result; +} \ No newline at end of file diff --git a/CPP/Array/Smallest subarray with sum greater than k.cpp b/CPP/Array/Smallest subarray with sum greater than k.cpp new file mode 100644 index 0000000..27d36f6 --- /dev/null +++ b/CPP/Array/Smallest subarray with sum greater than k.cpp @@ -0,0 +1,34 @@ +/* + link: https://practice.geeksforgeeks.org/problems/smallest-subarray-with-sum-greater-than-x5651/1 +*/ + + + +// ----------------------------------------------------------------------------------------------------------------------- // +// TC: O(n) + +// Returns length of smallest subarray with sum greater than x. If there is no subarray with given sum, then returns n+1 +int smallestSubWithSum(int arr[], int n, int x) +{ + // Initialize current sum and minimum length + int curr_sum = 0, min_len = n + 1; + + // Initialize starting and ending indexes + int start = 0, end = 0; + while (end < n) { + // Keep adding array elements while current sum is smaller than or equal to x + while (curr_sum <= x && end < n) + curr_sum += arr[end++]; + + // If current sum becomes greater than x. + while (curr_sum > x && start < n) { + // Update minimum length if needed + if (end - start < min_len) + min_len = end - start; + + // remove starting elements + curr_sum -= arr[start++]; + } + } + return min_len; +} diff --git a/CPP/Array/Subarray with sum 0.cpp b/CPP/Array/Subarray with sum 0.cpp new file mode 100644 index 0000000..e16fb57 --- /dev/null +++ b/CPP/Array/Subarray with sum 0.cpp @@ -0,0 +1,53 @@ +/* + link: https://practice.geeksforgeeks.org/problems/subarray-with-0-sum-1587115621/1 +*/ + + + +// ----------------------------------------------------------------------------------------------------------------------- // +bool subArrayExists(int arr[], int n) +{ + // if the element 0 itself is present. + for (int i = 0;i < n;i++) { + if (arr[i] == 0) return 1; + } + set s; + s.insert(arr[0]); + for (int i = 1;i < n;i++) { + arr[i] += arr[i - 1]; + + // + if (s.find(arr[i]) != s.end() || arr[i] == 0) return 1; + s.insert(arr[i]); + } + return 0; +} + + + +// ----------------------------------------------------------------------------------------------------------------------- // +// alternate solution +bool subArrayExists(int arr[], int n) +{ + //using map to store the prefix sum which has appeared already. + unordered_map sumMap; + + int sum = 0; + //iterating over the array. + for (int i = 0; i < n; i++) + { + //storing prefix sum. + sum += arr[i]; + + //if prefix sum is 0 or if it is already present in map then it is + //repeated which means there is a subarray whose summation is 0, + //so we return true. + if (sum == 0 || sumMap[sum] == true) + return true; + + //storing true in map for every prefix sum obtained. + sumMap[sum] = true; + } + //returning false if we don't get any subarray with 0 sum. + return false; +} diff --git a/CPP/Array/Three way partitioning array.cpp b/CPP/Array/Three way partitioning array.cpp new file mode 100644 index 0000000..f88138c --- /dev/null +++ b/CPP/Array/Three way partitioning array.cpp @@ -0,0 +1,21 @@ +/* + link: https://practice.geeksforgeeks.org/problems/three-way-partitioning/1 +*/ + + + +// ----------------------------------------------------------------------------------------------------------------------- // +void threeWayPartition(vector& array, int a, int b) +{ + int low = 0, high = array.size() - 1, mid = 0; + + while (mid <= high) { + if (array[mid] < a) { + swap(array[mid++], array[low++]); // we r sure after swap we won't get b) { + swap(array[high--], array[mid]); // here it is possible that after swap we can get >b value again hence no increment in mid. + } + else mid++; + } +} \ No newline at end of file diff --git a/CPP/Array/Trap rain water problem.cpp b/CPP/Array/Trap rain water problem.cpp new file mode 100644 index 0000000..b1b6e05 --- /dev/null +++ b/CPP/Array/Trap rain water problem.cpp @@ -0,0 +1,26 @@ +/* + link: https://practice.geeksforgeeks.org/problems/trapping-rain-water-1587115621/1 +*/ + + + +// ----------------------------------------------------------------------------------------------------------------------- // +// here we keep left max and right max at that point to get how much max water can be hold at current position. +int trappingWater(int arr[], int n) { + int ans = 0; + int l[n], r[n]; + l[0] = arr[0]; + r[n - 1] = arr[n - 1]; + + for (int i = 1;i < n;i++) { + l[i] = max(arr[i], l[i - 1]); + } + for (int i = n - 2;i >= 0;i--) { + r[i] = max(arr[i], r[i + 1]); + } + + for (int i = 1;i < n - 1;i++) { + ans += max(0, min(l[i], r[i]) - arr[i]); + } + return ans; +} \ No newline at end of file diff --git a/CPP/Array/Triplet of element sum.cpp b/CPP/Array/Triplet of element sum.cpp new file mode 100644 index 0000000..0a4ca38 --- /dev/null +++ b/CPP/Array/Triplet of element sum.cpp @@ -0,0 +1,66 @@ +/* + link: https://practice.geeksforgeeks.org/problems/triplet-sum-in-array-1587115621/1 +*/ + + + +// ----------------------------------------------------------------------------------------------------------------------- // +// two pointer approach to find sum of the rest than pivoted ele in O(N) +bool findPairs(int a[], int sum, int l, int r) { + + while (l < r) { + int curr_sum = a[l] + a[r]; + if (curr_sum == sum) return true; + else if (curr_sum < sum) { + l++; + } + else r--; + } + return false; +} +bool find3Numbers(int a[], int n, int X) +{ + sort(a, a + n); + for (int i = 0;i < n - 2;i++) { + if (findPairs(a, X - a[i], i + 1, n - 1)) return true; + } + return false; +} + + + +// ----------------------------------------------------------------------------------------------------------------------- // +// alternate solution +bool find3Numbers(int A[], int n, int X) +{ + int l, r; + //Sorting the elements. + sort(A, A + n); + + //Traversing the array elements. + for (int i = 0; i < n - 2; i++) + { + //Taking two pointers. One at element after ith index and another + //at the last index. + l = i + 1; + r = n - 1; + while (l < r) + { + //If sum of elements at indexes i, l and r is equal + //to required number, we return true. + if (A[i] + A[l] + A[r] == X) + return true; + //Else if the sum is less than required number, it means we need + //to increase the sum so we increase the left pointer l. + else if (A[i] + A[l] + A[r] < X) + l++; + //Else the sum is more than required number and we need to + //decrease the sum so we decrease the right pointer r. + else + r--; + } + } + + //returning false if no triplet sum equal to required number is present. + return false; +} \ No newline at end of file From b151e35227072cd81ddd51bee868c3b6cfb0c95e Mon Sep 17 00:00:00 2001 From: Akash Gautam <76935019+geekblower@users.noreply.github.com> Date: Thu, 20 Oct 2022 09:44:50 +0530 Subject: [PATCH 2/4] Binary Tree codes in CPP --- CPP/Binary Tree/Bottom view of tree.cpp | 61 ++++ ... trees from inorder preorder traversal.cpp | 323 ++++++++++++++++++ CPP/Binary Tree/Diameter of tree.cpp | 139 ++++++++ CPP/Binary Tree/Find LCA in BT.cpp | 216 ++++++++++++ CPP/Binary Tree/Height of tree.cpp | 34 ++ .../Largest subtree sum in tree.cpp | 95 ++++++ CPP/Binary Tree/Left view of tree.cpp | 163 +++++++++ CPP/Binary Tree/Level order traversal.cpp | 158 +++++++++ ... require to convert binary tree to BST.cpp | 72 ++++ CPP/Binary Tree/Mirror of tree.cpp | 165 +++++++++ .../Print all K sum path in BT.cpp | 95 ++++++ .../Reverse level order traversal.cpp | 99 ++++++ CPP/Binary Tree/Right view of tree.cpp | 122 +++++++ CPP/Binary Tree/Top view of tree.cpp | 228 +++++++++++++ CPP/Binary Tree/Trees isomorphism problem.cpp | 91 +++++ 15 files changed, 2061 insertions(+) create mode 100644 CPP/Binary Tree/Bottom view of tree.cpp create mode 100644 CPP/Binary Tree/Construct binary trees from inorder preorder traversal.cpp create mode 100644 CPP/Binary Tree/Diameter of tree.cpp create mode 100644 CPP/Binary Tree/Find LCA in BT.cpp create mode 100644 CPP/Binary Tree/Height of tree.cpp create mode 100644 CPP/Binary Tree/Largest subtree sum in tree.cpp create mode 100644 CPP/Binary Tree/Left view of tree.cpp create mode 100644 CPP/Binary Tree/Level order traversal.cpp create mode 100644 CPP/Binary Tree/Minimum swaps require to convert binary tree to BST.cpp create mode 100644 CPP/Binary Tree/Mirror of tree.cpp create mode 100644 CPP/Binary Tree/Print all K sum path in BT.cpp create mode 100644 CPP/Binary Tree/Reverse level order traversal.cpp create mode 100644 CPP/Binary Tree/Right view of tree.cpp create mode 100644 CPP/Binary Tree/Top view of tree.cpp create mode 100644 CPP/Binary Tree/Trees isomorphism problem.cpp diff --git a/CPP/Binary Tree/Bottom view of tree.cpp b/CPP/Binary Tree/Bottom view of tree.cpp new file mode 100644 index 0000000..051701a --- /dev/null +++ b/CPP/Binary Tree/Bottom view of tree.cpp @@ -0,0 +1,61 @@ +/* + link: https://practice.geeksforgeeks.org/problems/bottom-view-of-binary-tree/1 + + sol: https://www.geeksforgeeks.org/bottom-view-binary-tree/ + + while doing problems of top and bottom view nodes might overlap as, + + a + / \ + b c + \ / + d,e + here d from b side and e from c side. +*/ + + + +// ----------------------------------------------------------------------------------------------------------------------- // +void printBottomViewUtil(Node* root, int curr, int hd, map >& m) +{ + // Base case + if (root == NULL) + return; + + // If node for a particular + // horizontal distance is not + // present, add to the map. + if (m.find(hd) == m.end()) + { + m[hd] = make_pair(root->data, curr); + } + // Compare height for already + // present node at similar horizontal + // distance, if its smaller or same replace it. + else if (m[hd].second <= curr) m[hd] = make_pair(root->data, curr); + + + // Recur for left subtree + printBottomViewUtil(root->left, curr + 1, hd - 1, m); + + // Recur for right subtree + printBottomViewUtil(root->right, curr + 1, hd + 1, m); +} + +void printBottomView(Node* root) +{ + + // Map to store Horizontal Distance, + // Height and Data. + map < int, pair < int, int > > m; + + printBottomViewUtil(root, 0, 0, m); + + // Prints the values stored by printBottomViewUtil() + map < int, pair < int, int > > ::iterator it; + for (it = m.begin(); it != m.end(); ++it) + { + pair < int, int > p = it->second; + cout << p.first << " "; + } +} \ No newline at end of file diff --git a/CPP/Binary Tree/Construct binary trees from inorder preorder traversal.cpp b/CPP/Binary Tree/Construct binary trees from inorder preorder traversal.cpp new file mode 100644 index 0000000..e99b09d --- /dev/null +++ b/CPP/Binary Tree/Construct binary trees from inorder preorder traversal.cpp @@ -0,0 +1,323 @@ +/* + link: https://practice.geeksforgeeks.org/problems/construct-tree-1/1 + + sol: https://www.geeksforgeeks.org/construct-tree-from-given-inorder-and-preorder-traversal/ +*/ + + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + Accepted solution (other are correct code but showing segmentation error, figured a lot but... :<( ) +*/ +int findIndex(int arr[], int start, int target) +{ + int i = 0; + while (arr[start + i] != target) i++; + return i; +} + +Node* buildUtil(int inorder[], int preorder[], int inStart, int preStart, int n) +{ + if (n == 0) return NULL; + + Node* ret = new Node(preorder[preStart]); + + int i = findIndex(inorder, inStart, preorder[preStart]); + + ret->left = buildUtil(inorder, preorder, inStart, preStart + 1, i); + ret->right = buildUtil(inorder, preorder, inStart + i + 1, preStart + i + 1, n - i - 1); + + return ret; +} + +Node* buildTree(int inorder[], int preorder[], int n) +{ + return buildUtil(inorder, preorder, 0, 0, n); +} + + + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + using index + + TC: O(N^2) +*/ + +/* A binary tree node has data, pointer to left child +and a pointer to right child */ +class node +{ + public: + char data; + node* left; + node* right; +}; + +/* Prototypes for utility functions */ +int search(char arr[], int strt, int end, char value); +node* newNode(char data); + +/* Recursive function to construct binary +of size len from Inorder traversal in[] +and Preorder traversal pre[]. Initial values +of inStrt and inEnd should be 0 and len -1. +The function doesn't do any error checking +for cases where inorder and preorder do not +form a tree */ +node* buildTree(char in[], char pre[], int inStrt, int inEnd) +{ + static int preIndex = 0; + + if (inStrt > inEnd) + return NULL; + + /* Pick current node from Preorder + traversal using preIndex + and increment preIndex */ + node* tNode = newNode(pre[preIndex++]); + + /* If this node has no children then return */ + if (inStrt == inEnd) + return tNode; + + /* Else find the index of this node in Inorder traversal */ + int inIndex = search(in, inStrt, inEnd, tNode->data); + + /* Using index in Inorder traversal, construct left and + right subtress */ + tNode->left = buildTree(in, pre, inStrt, inIndex - 1); + tNode->right = buildTree(in, pre, inIndex + 1, inEnd); + + return tNode; +} + +/* UTILITY FUNCTIONS */ +/* Function to find index of value in arr[start...end] +The function assumes that value is present in in[] */ +int search(char arr[], int strt, int end, char value) +{ + int i; + for (i = strt; i <= end; i++) + { + if (arr[i] == value) + return i; + } +} + +/* Helper function that allocates a new node with the +given data and NULL left and right pointers. */ +node* newNode(char data) +{ + node* Node = new node(); + Node->data = data; + Node->left = NULL; + Node->right = NULL; + + return (Node); +} + +/* This funtcion is here just to test buildTree() */ +void printInorder(node* node) +{ + if (node == NULL) + return; + + /* first recur on left child */ + printInorder(node->left); + + /* then print the data of node */ + cout << node->data << " "; + + /* now recur on right child */ + printInorder(node->right); +} + +/* Driver code */ +int main() +{ + char in[] = { 'D', 'B', 'E', 'A', 'F', 'C' }; + char pre[] = { 'A', 'B', 'D', 'E', 'C', 'F' }; + int len = sizeof(in) / sizeof(in[0]); + node* root = buildTree(in, pre, 0, len - 1); + + /* Let us test the built tree by + printing Insorder traversal */ + cout << "Inorder traversal of the constructed tree is \n"; + printInorder(root); +} + + + + + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + using hashing (to search in O(1)) + TC: O(N) +*/ +/* C++ program to construct tree using inorder +and preorder traversals */ +#include +using namespace std; + +/* A binary tree node has data, pointer to left child +and a pointer to right child */ +struct Node { + char data; + struct Node* left; + struct Node* right; +}; + +struct Node* newNode(char data) +{ + struct Node* node = new Node; + node->data = data; + node->left = node->right = NULL; + return (node); +} + +/* Recursive function to construct binary of size +len from Inorder traversal in[] and Preorder traversal +pre[]. Initial values of inStrt and inEnd should be +0 and len -1. The function doesn't do any error +checking for cases where inorder and preorder +do not form a tree */ +struct Node* buildTree(char in[], char pre[], int inStrt, + int inEnd, unordered_map& mp) +{ + static int preIndex = 0; + + if (inStrt > inEnd) + return NULL; + + /* Pick current node from Preorder traversal using preIndex + and increment preIndex */ + char curr = pre[preIndex++]; + struct Node* tNode = newNode(curr); + + /* If this node has no children then return */ + if (inStrt == inEnd) + return tNode; + + /* Else find the index of this node in Inorder traversal */ + int inIndex = mp[curr]; + + /* Using index in Inorder traversal, construct left and + right subtress */ + tNode->left = buildTree(in, pre, inStrt, inIndex - 1, mp); + tNode->right = buildTree(in, pre, inIndex + 1, inEnd, mp); + + return tNode; +} + +// This function mainly creates an unordered_map, then +// calls buildTree() +struct Node* buldTreeWrap(char in[], char pre[], int len) +{ + // Store indexes of all items so that we + // we can quickly find later + unordered_map mp; + for (int i = 0; i < len; i++) + mp[in[i]] = i; + + return buildTree(in, pre, 0, len - 1, mp); +} + +/* This funtcion is here just to test buildTree() */ +void printInorder(struct Node* node) +{ + if (node == NULL) + return; + printInorder(node->left); + printf("%c ", node->data); + printInorder(node->right); +} + +/* Driver program to test above functions */ +int main() +{ + char in[] = { 'D', 'B', 'E', 'A', 'F', 'C' }; + char pre[] = { 'A', 'B', 'D', 'E', 'C', 'F' }; + int len = sizeof(in) / sizeof(in[0]); + + struct Node* root = buldTreeWrap(in, pre, len); + + /* Let us test the built tree by printing + Insorder traversal */ + printf("Inorder traversal of the constructed tree is \n"); + printInorder(root); +} + + + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + using stack and queue +*/ + +set s; +stack st; + +// Function to build tree using given traversal +TreeNode* buildTree(int preorder[], int inorder[], int n) +{ + + TreeNode* root = NULL; + for (int pre = 0, in = 0; pre < n;) + { + + TreeNode* node = NULL; + do + { + node = new TreeNode(preorder[pre]); + if (root == NULL) + { + root = node; + } + if (st.size() > 0) + { + if (s.find(st.top()) != s.end()) + { + s.erase(st.top()); + st.top()->right = node; + st.pop(); + } + else + { + st.top()->left = node; + } + } + st.push(node); + } while (preorder[pre++] != inorder[in] && pre < n); + + node = NULL; + while (st.size() > 0 && in < n && + st.top()->val == inorder[in]) + { + node = st.top(); + st.pop(); + in++; + } + + if (node != NULL) + { + s.insert(node); + st.push(node); + } + } + + return root; +} \ No newline at end of file diff --git a/CPP/Binary Tree/Diameter of tree.cpp b/CPP/Binary Tree/Diameter of tree.cpp new file mode 100644 index 0000000..d80d616 --- /dev/null +++ b/CPP/Binary Tree/Diameter of tree.cpp @@ -0,0 +1,139 @@ +/* + link: https://practice.geeksforgeeks.org/problems/diameter-of-binary-tree/1 + + sol: https://www.geeksforgeeks.org/diameter-of-a-binary-tree/ +*/ + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + using recursion + TC: O(N) + SC: O(1) +*/ +int subTreesHeight(Node* n, int* dia) +{ + // if node becomes null, we return 0. + if (!n) return 0; + + // calling the go function recursively for the left and + // right subtrees to find their heights. + int l = subTreesHeight(n->left, dia); + int r = subTreesHeight(n->right, dia); + + // storing the maximum possible value of l+r+1 in diameter. + if (l + r + 1 > *dia) *dia = l + r + 1; + + // returning height of subtree. + return 1 + max(l, r); +} + + +// Function to return the diameter of a Binary Tree. +int diameter(Node* root) +{ + int dia = 0; + // calling the function to find the result. + subTreesHeight(root, &dia); + // returning the result. + return dia; +} + + + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + using recursion (but if called height everytime) + TC: O(N^2) + SC: O(1) +*/ + +// The function Compute the "height" of a tree. Height is +// the number f nodes along the longest path from the root +// node down to the farthest leaf node. +int height(struct node* node) +{ + // base case tree is empty + if (node == NULL) + return 0; + + // If tree is not empty then height = 1 + max of left + // height and right heights + return 1 + max(height(node->left), height(node->right)); +} + +// Function to get diameter of a binary tree +int diameter(struct node* tree) +{ + // base case where tree is empty + if (tree == NULL) + return 0; + + // get the height of left and right sub-trees + int lheight = height(tree->left); + int rheight = height(tree->right); + + // get the diameter of left and right sub-trees + int ldiameter = diameter(tree->left); + int rdiameter = diameter(tree->right); + + // Return max of following three + // 1) Diameter of left subtree + // 2) Diameter of right subtree + // 3) Height of left subtree + height of right subtree + 1 (plus 1 for the root itself) + return max({ lheight + rheight + 1, ldiameter, rdiameter }); +} + + + + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + using queue + TC: O(N^2) + SC: O(N) +*/ +int height(struct Node* node) +{ + if (node == NULL) return 0; + else { + int lHeight = height(node->left); + int rHeight = height(node->right); + + return (lHeight > rHeight) ? lHeight + 1 : rHeight + 1; + } +} + +//Function to return the diameter of a Binary Tree. +int diameter(Node* root) +{ +// Your code here + Node* temp; + queue q; + q.push(root); + int mx = INT_MIN, lh, rh; + + while (q.size()) { + temp = q.front(); + + // find height of subtrees of root. + lh = height(temp->left); + rh = height(temp->right); + + // pushing left subtree and right subtree address. + if (temp->left) q.push(temp->left); + if (temp->right) q.push(temp->right); + + // storing maximum of the prev and current diameter. + mx = max(mx, lh + rh + 1); + q.pop(); + } + return mx; +} \ No newline at end of file diff --git a/CPP/Binary Tree/Find LCA in BT.cpp b/CPP/Binary Tree/Find LCA in BT.cpp new file mode 100644 index 0000000..8c73cbc --- /dev/null +++ b/CPP/Binary Tree/Find LCA in BT.cpp @@ -0,0 +1,216 @@ +/* + link: https://practice.geeksforgeeks.org/problems/lowest-common-ancestor-in-a-binary-tree/1 +*/ + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + storing and comparing path of n1 and n2 + TC: O(N) + SC: O(N) +*/ +// C++ Program for Lowest Common Ancestor in a Binary Tree +// A O(n) solution to find LCA of two given values n1 and n2 +#include +#include + +using namespace std; + +// A Binary Tree node +struct Node +{ + int key; + struct Node* left, * right; +}; + +// Utility function creates a new binary tree node with given key +Node* newNode(int k) +{ + Node* temp = new Node; + temp->key = k; + temp->left = temp->right = NULL; + return temp; +} + +// Finds the path from root node to given root of the tree, Stores the +// path in a vector path[], returns true if path exists otherwise false +bool findPath(Node* root, vector& path, int k) +{ + // base case + if (root == NULL) return false; + + // Store this node in path vector. The node will be removed if + // not in path from root to k + path.push_back(root->key); + + // See if the k is same as root's key + if (root->key == k) + return true; + + // Check if k is found in left or right sub-tree + if ((root->left && findPath(root->left, path, k)) || + (root->right && findPath(root->right, path, k))) + return true; + + // If not present in subtree rooted with root, remove root from + // path[] and return false + path.pop_back(); + return false; +} + +// Returns LCA if node n1, n2 are present in the given binary tree, +// otherwise return -1 +int findLCA(Node* root, int n1, int n2) +{ + // to store paths to n1 and n2 from the root + vector path1, path2; + + // Find paths from root to n1 and root to n1. If either n1 or n2 + // is not present, return -1 + if (!findPath(root, path1, n1) || !findPath(root, path2, n2)) + return -1; + + /* Compare the paths to get the first different value */ + int i; + for (i = 0; i < path1.size() && i < path2.size(); i++) + if (path1[i] != path2[i]) + break; + return path1[i - 1]; +} + +// Driver program to test above functions +int main() +{ + // Let us create the Binary Tree shown in above diagram. + Node* root = newNode(1); + root->left = newNode(2); + root->right = newNode(3); + root->left->left = newNode(4); + root->left->right = newNode(5); + root->right->left = newNode(6); + root->right->right = newNode(7); + cout << "LCA(4, 5) = " << findLCA(root, 4, 5); + cout << "nLCA(4, 6) = " << findLCA(root, 4, 6); + cout << "nLCA(3, 4) = " << findLCA(root, 3, 4); + cout << "nLCA(2, 4) = " << findLCA(root, 2, 4); + return 0; +} + + + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + finding in single traversal (assuming that keys are present) + TC: O(N) + SC: O(1) +*/ +// This function returns pointer to LCA of two given values n1 and n2. +// This function assumes that n1 and n2 are present in Binary Tree +struct Node* findLCA(struct Node* root, int n1, int n2) +{ + // Base case + if (root == NULL) return NULL; + + // If either n1 or n2 matches with root's key, report + // the presence by returning root (Note that if a key is + // ancestor of other, then the ancestor key becomes LCA + if (root->key == n1 || root->key == n2) + return root; + + // Look for keys in left and right subtrees + Node* left_lca = findLCA(root->left, n1, n2); + Node* right_lca = findLCA(root->right, n1, n2); + + // If both of the above calls return Non-NULL, then one key + // is present in once subtree and other is present in other, + // So this node is the LCA + if (left_lca && right_lca) return root; + + // Otherwise check if left subtree or right subtree is LCA + return (left_lca != NULL) ? left_lca : right_lca; +} + + + + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + also proving if keys are present or not +*/ + +// This function returns pointer to LCA of two given values n1 and n2. +// v1 is set as true by this function if n1 is found +// v2 is set as true by this function if n2 is found +struct Node* findLCAUtil(struct Node* root, int n1, int n2, bool& v1, bool& v2) +{ + // Base case + if (root == NULL) return NULL; + + // If either n1 or n2 matches with root's key, report the presence + // by setting v1 or v2 as true and return root (Note that if a key + // is ancestor of other, then the ancestor key becomes LCA) + if (root->key == n1) + { + v1 = true; + return root; + } + if (root->key == n2) + { + v2 = true; + return root; + } + + // Look for keys in left and right subtrees + Node* left_lca = findLCAUtil(root->left, n1, n2, v1, v2); + Node* right_lca = findLCAUtil(root->right, n1, n2, v1, v2); + + // If both of the above calls return Non-NULL, then one key + // is present in once subtree and other is present in other, + // So this node is the LCA + if (left_lca && right_lca) return root; + + // Otherwise check if left subtree or right subtree is LCA + return (left_lca != NULL) ? left_lca : right_lca; +} + +// Returns true if key k is present in tree rooted with root +bool find(Node* root, int k) +{ + // Base Case + if (root == NULL) + return false; + + // If key is present at root, or in left subtree or right subtree, + // return true; + if (root->key == k || find(root->left, k) || find(root->right, k)) + return true; + + // Else return false + return false; +} + +// This function returns LCA of n1 and n2 only if both n1 and n2 are present +// in tree, otherwise returns NULL; +Node* findLCA(Node* root, int n1, int n2) +{ + // Initialize n1 and n2 as not visited + bool v1 = false, v2 = false; + + // Find lca of n1 and n2 using the technique discussed above + Node* lca = findLCAUtil(root, n1, n2, v1, v2); + + // Return LCA only if both n1 and n2 are present in tree + if (v1 && v2 || v1 && find(lca, n2) || v2 && find(lca, n1)) + return lca; + + // Else return NULL + return NULL; +} diff --git a/CPP/Binary Tree/Height of tree.cpp b/CPP/Binary Tree/Height of tree.cpp new file mode 100644 index 0000000..86e22d7 --- /dev/null +++ b/CPP/Binary Tree/Height of tree.cpp @@ -0,0 +1,34 @@ +/* + link: https://practice.geeksforgeeks.org/problems/height-of-binary-tree/1 + + sol: https://www.geeksforgeeks.org/write-a-c-program-to-find-the-maximum-depth-or-height-of-a-tree/ + + **note**: maximum depth of tree === height of the tree. +*/ + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + TC: O(N) +*/ +int height(struct Node* node) +{ + // if node is null, we return 0. + if (node == NULL) return 0; + + //else we call the recursive function, height for left and right + //subtree and choose their maximum. we also add 1 to the result + //which indicates height of root of the tree. + else { + int lHeight = height(node->left); + int rHeight = height(node->right); + + if (lHeight > rHeight) { + return lHeight + 1; + } + else { + return rHeight + 1; + } + } +} diff --git a/CPP/Binary Tree/Largest subtree sum in tree.cpp b/CPP/Binary Tree/Largest subtree sum in tree.cpp new file mode 100644 index 0000000..02a3b17 --- /dev/null +++ b/CPP/Binary Tree/Largest subtree sum in tree.cpp @@ -0,0 +1,95 @@ +/* + link: https://www.geeksforgeeks.org/find-largest-subtree-sum-tree/ +*/ + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + Time Complexity: O(n), where n is number of nodes. + Auxiliary Space: O(n), function call stack size. +*/ +// C++ program to find largest subtree +// sum in a given binary tree. +#include +using namespace std; + +// Structure of a tree node. +struct Node { + int key; + Node* left, * right; +}; + +// Function to create new tree node. +Node* newNode(int key) +{ + Node* temp = new Node; + temp->key = key; + temp->left = temp->right = NULL; + return temp; +} + +// Helper function to find largest +// subtree sum recursively. +int findLargestSubtreeSumUtil(Node* root, int& ans) +{ + // If current node is null then + // return 0 to parent node. + if (root == NULL) + return 0; + + // Subtree sum rooted at current node. + int currSum = root->key + findLargestSubtreeSumUtil(root->left, ans) + findLargestSubtreeSumUtil(root->right, ans); + + // Update answer if current subtree + // sum is greater than answer so far. + ans = max(ans, currSum); + + // Return current subtree sum to + // its parent node. + return currSum; +} + +// Function to find largest subtree sum. +int findLargestSubtreeSum(Node* root) +{ + // If tree does not exist, + // then answer is 0. + if (root == NULL) + return 0; + + // Variable to store maximum subtree sum. + int ans = INT_MIN; + + // Call to recursive function to + // find maximum subtree sum. + findLargestSubtreeSumUtil(root, ans); + + return ans; +} + +// Driver function +int main() +{ + /* + 1 + / \ + / \ + -2 3 + / \ / \ + / \ / \ + 4 5 -6 2 + */ + + Node* root = newNode(1); + root->left = newNode(-2); + root->right = newNode(3); + root->left->left = newNode(4); + root->left->right = newNode(5); + root->right->left = newNode(-6); + root->right->right = newNode(2); + + cout << findLargestSubtreeSum(root); + return 0; +} diff --git a/CPP/Binary Tree/Left view of tree.cpp b/CPP/Binary Tree/Left view of tree.cpp new file mode 100644 index 0000000..cc922e6 --- /dev/null +++ b/CPP/Binary Tree/Left view of tree.cpp @@ -0,0 +1,163 @@ +/* + link: https://practice.geeksforgeeks.org/problems/left-view-of-binary-tree/1 + + sol: https://www.geeksforgeeks.org/print-left-view-binary-tree/ +*/ + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + using recursion +*/ +// C++ program to print left view of Binary Tree +#include +using namespace std; + +struct Node +{ + int data; + struct Node* left, * right; +}; + +// A utility function to +// create a new Binary Tree Node +struct Node* newNode(int item) +{ + struct Node* temp = (struct Node*)malloc( + sizeof(struct Node)); + temp->data = item; + temp->left = temp->right = NULL; + return temp; +} + +// Recursive function to print +// left view of a binary tree. +void leftViewUtil(struct Node* root, + int level, int* max_level) +{ + // Base Case + if (root == NULL) return; + + // If this is the first Node of its level + if (*max_level < level) + { + cout << root->data << " "; + *max_level = level; + } + + // Recur for left subtree first, + // then right subtree + leftViewUtil(root->left, level + 1, max_level); + leftViewUtil(root->right, level + 1, max_level); + +} + +// A wrapper over leftViewUtil() +void leftView(struct Node* root) +{ + int max_level = 0; + leftViewUtil(root, 1, &max_level); +} + +// Driver Code +int main() +{ + Node* root = newNode(10); + root->left = newNode(2); + root->right = newNode(3); + root->left->left = newNode(7); + root->left->right = newNode(8); + root->right->right = newNode(15); + root->right->left = newNode(12); + root->right->right->left = newNode(14); + + leftView(root); + + return 0; +} + + + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + using queue +*/ +// C++ program to print left view of +// Binary Tree + +#include +using namespace std; + +// A Binary Tree Node +struct Node +{ + int data; + struct Node* left, * right; +}; + +// Utility function to create a new tree node +Node* newNode(int data) +{ + Node* temp = new Node; + temp->data = data; + temp->left = temp->right = NULL; + return temp; +} + +// function to print left view of +// binary tree +void printLeftView(Node* root) +{ + if (!root) + return; + + queue q; + q.push(root); + + while (!q.empty()) + { + // number of nodes at current level + int n = q.size(); + + // Traverse all nodes of current level + for (int i = 1; i <= n; i++) + { + Node* temp = q.front(); + q.pop(); + + // Print the left most element + // at the level + if (i == 1) + cout << temp->data << " "; + + // Add left node to queue + if (temp->left != NULL) + q.push(temp->left); + + // Add right node to queue + if (temp->right != NULL) + q.push(temp->right); + } + } +} + +// Driver code +int main() +{ + // Let's construct the tree as + // shown in example + + Node* root = newNode(10); + root->left = newNode(2); + root->right = newNode(3); + root->left->left = newNode(7); + root->left->right = newNode(8); + root->right->right = newNode(15); + root->right->left = newNode(12); + root->right->right->left = newNode(14); + + printLeftView(root); +} diff --git a/CPP/Binary Tree/Level order traversal.cpp b/CPP/Binary Tree/Level order traversal.cpp new file mode 100644 index 0000000..5b6860d --- /dev/null +++ b/CPP/Binary Tree/Level order traversal.cpp @@ -0,0 +1,158 @@ +/* + link: https://practice.geeksforgeeks.org/problems/level-order-traversal/1 + + sol: https://www.geeksforgeeks.org/level-order-tree-traversal/ +*/ + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + by printing current level + + Time Complexity: O(n^2) in worst case. For a skewed tree, printGivenLevel() takes + O(n) time where n is the number of nodes in the skewed tree. + So time complexity of printLevelOrder() is O(n) + O(n-1) + O(n-2) + .. + O(1) which is O(n^2). + + Space Complexity: O(n) in worst case. For a skewed tree, printGivenLevel() uses + O(n) space for call stack. For a Balanced tree, the call stack uses O(log n) space, + (i.e., the height of the balanced tree). +*/ +// Recursive CPP program for level +// order traversal of Binary Tree +#include +using namespace std; + +/* A binary tree node has data, +pointer to left child +and a pointer to right child */ +class node +{ +public: + int data; + node* left, * right; +}; + +/* Function protoypes */ +void printCurrentLevel(node* root, int level); +int height(node* node); +node* newNode(int data); + +/* Function to print level +order traversal a tree*/ +void printLevelOrder(node* root) +{ + int h = height(root); + int i; + for (i = 1; i <= h; i++) + printCurrentLevel(root, i); +} + +/* Print nodes at a current level */ +void printCurrentLevel(node* root, int level) +{ + if (root == NULL) + return; + if (level == 1) + cout << root->data << " "; + else if (level > 1) + { + printCurrentLevel(root->left, level - 1); + printCurrentLevel(root->right, level - 1); + } +} + +/* Compute the "height" of a tree -- the number of + nodes along the longest path from the root node + down to the farthest leaf node.*/ +int height(node* node) +{ + if (node == NULL) + return 0; + else + { + /* compute the height of each subtree */ + int lheight = height(node->left); + int rheight = height(node->right); + + /* use the larger one */ + if (lheight > rheight) + { + return(lheight + 1); + } + else { + return(rheight + 1); + } + } +} + +/* Helper function that allocates +a new node with the given data and +NULL left and right pointers. */ +node* newNode(int data) +{ + node* Node = new node(); + Node->data = data; + Node->left = NULL; + Node->right = NULL; + + return(Node); +} + +/* Driver code*/ +int main() +{ + node* root = newNode(1); + root->left = newNode(2); + root->right = newNode(3); + root->left->left = newNode(4); + root->left->right = newNode(5); + + cout << "Level Order traversal of binary tree is \n"; + printLevelOrder(root); + + return 0; +} + + + + + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + using queue + TC: O(N) + SC: O(N) + ---> where n is the number of nodes in the binary trees +*/ +void printLevelOrder(Node* root) +{ + // Base Case + if (root == NULL) return; + + // Create an empty queue for level order traversal + queue q; + + // Enqueue Root and initialize height + q.push(root); + + while (q.empty() == false) + { + // Print front of queue and remove it from queue + Node* node = q.front(); + cout << node->data << " "; + q.pop(); + + /* Enqueue left child */ + if (node->left != NULL) + q.push(node->left); + + /*Enqueue right child */ + if (node->right != NULL) + q.push(node->right); + } +} \ No newline at end of file diff --git a/CPP/Binary Tree/Minimum swaps require to convert binary tree to BST.cpp b/CPP/Binary Tree/Minimum swaps require to convert binary tree to BST.cpp new file mode 100644 index 0000000..cd123c1 --- /dev/null +++ b/CPP/Binary Tree/Minimum swaps require to convert binary tree to BST.cpp @@ -0,0 +1,72 @@ +/* + link: https://www.geeksforgeeks.org/minimum-swap-required-convert-binary-tree-binary-search-tree/ + + sorting inorder traversal of tree => Binary Search Tree + or + sort the array and then arrange it in inorder => BST + + + basically here logic is to get inorder of tree, then sort it and compare it with itself to know the swaps +*/ + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +// C++ program for Minimum swap required +// to convert binary tree to binary search tree +#include +using namespace std; + +// Inorder Traversal of Binary Tree +void inorder(int a[], std::vector& v, + int n, int index) +{ + // if index is greater or equal to vector size + if (index >= n) + return; + inorder(a, v, n, 2 * index + 1); + + // push elements in vector + v.push_back(a[index]); + inorder(a, v, n, 2 * index + 2); +} + +// Function to find minimum swaps to sort an array +int minSwaps(std::vector& v) +{ + std::vector > t(v.size()); + int ans = 0; + for (int i = 0; i < v.size(); i++) + t[i].first = v[i], t[i].second = i; + + sort(t.begin(), t.end()); + for (int i = 0; i < t.size(); i++) + { + // second element is equal to i + if (i == t[i].second) + continue; + else + { + // swaping of elements + swap(t[i].first, t[t[i].second].first); + swap(t[i].second, t[t[i].second].second); + } + + // Second is not equal to i + if (i != t[i].second) + --i; + ans++; + } + return ans; +} + +// Driver code +int main() +{ + int a[] = { 5, 6, 7, 8, 9, 10, 11 }; + int n = sizeof(a) / sizeof(a[0]); + std::vector v; + inorder(a, v, n, 0); + cout << minSwaps(v) << endl; +} diff --git a/CPP/Binary Tree/Mirror of tree.cpp b/CPP/Binary Tree/Mirror of tree.cpp new file mode 100644 index 0000000..9d3fd1b --- /dev/null +++ b/CPP/Binary Tree/Mirror of tree.cpp @@ -0,0 +1,165 @@ +/* + link: https://www.geeksforgeeks.org/create-a-mirror-tree-from-the-given-binary-tree/ +*/ + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + by swapping the left and right sub-tree +*/ + +#include +using namespace std; + +typedef struct treenode { + int val; + struct treenode* left; + struct treenode* right; +} node; + +// Helper function that +// allocates a new node with the +// given data and NULL left and right pointers +node* createNode(int val) +{ + node* newNode = (node*)malloc(sizeof(node)); + newNode->val = val; + newNode->left = NULL; + newNode->right = NULL; + return newNode; +} + +// Function to print the inrder traversal +void inorder(node* root) +{ + if (root == NULL) + return; + inorder(root->left); + printf("%d ", root->val); + inorder(root->right); +} + +// Function to convert to mirror tree +treenode* mirrorTree(node* root) +{ + // Base Case + if (root == NULL) + return root; + node* t = root->left; + root->left = root->right; + root->right = t; + + if (root->left) + mirrorTree(root->left); + if (root->right) + mirrorTree(root->right); + + return root; +} + +// Driver Code +int main() +{ + + node* tree = createNode(5); + tree->left = createNode(3); + tree->right = createNode(6); + tree->left->left = createNode(2); + tree->left->right = createNode(4); + printf("Inorder of original tree: "); + inorder(tree); + + // Function call + mirrorTree(tree); + + printf("\nInorder of Miror tree: "); + inorder(tree); + return 0; +} + + + + + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + by making separate mirror tree +*/ +// C implementation of the approach +#include +#include + +// A binary tree node has data, pointer to +// left child and a pointer to right child +typedef struct treenode { + int val; + struct treenode* left; + struct treenode* right; +} node; + +// Helper function that allocates a new node with the +// given data and NULL left and right pointers +node* createNode(int val) +{ + node* newNode = (node*)malloc(sizeof(node)); + newNode->val = val; + newNode->left = NULL; + newNode->right = NULL; + return newNode; +} + +// Helper function to print Inorder traversal +void inorder(node* root) +{ + if (root == NULL) + return; + inorder(root->left); + printf("%d ", root->val); + inorder(root->right); +} + +// mirrorify function takes two trees, +// original tree and a mirror tree +// It recurses on both the trees, +// but when original tree recurses on left, +// mirror tree recurses on right and +// vice-versa +void mirrorify(node* root, node** mirror) +{ + if (root == NULL) { + mirror = NULL; + return; + } + + // Create new mirror node from original tree node + *mirror = createNode(root->val); + mirrorify(root->left, &((*mirror)->right)); + mirrorify(root->right, &((*mirror)->left)); +} + +// Driver code +int main() +{ + + node* tree = createNode(5); + tree->left = createNode(3); + tree->right = createNode(6); + tree->left->left = createNode(2); + tree->left->right = createNode(4); + + // Print inorder traversal of the input tree + printf("Inorder of original tree: "); + inorder(tree); + node* mirror = NULL; + mirrorify(tree, &mirror); + + // Print inorder traversal of the mirror tree + printf("\nInorder of mirror tree: "); + inorder(mirror); + + return 0; +} diff --git a/CPP/Binary Tree/Print all K sum path in BT.cpp b/CPP/Binary Tree/Print all K sum path in BT.cpp new file mode 100644 index 0000000..ba85f19 --- /dev/null +++ b/CPP/Binary Tree/Print all K sum path in BT.cpp @@ -0,0 +1,95 @@ +/* + link: https://www.geeksforgeeks.org/print-k-sum-paths-binary-tree/ +*/ + + + +// ----------------------------------------------------------------------------------------------------------------------- // +// C++ program to print all paths with sum k. +#include +using namespace std; + +//utility function to print contents of +//a vector from index i to it's end +void printVector(const vector& v, int i) +{ + for (int j = i; j < v.size(); j++) + cout << v[j] << " "; + cout << endl; +} + +// binary tree node +struct Node +{ + int data; + Node* left, * right; + Node(int x) + { + data = x; + left = right = NULL; + } +}; + +// This function prints all paths that have sum k +void printKPathUtil(Node* root, vector& path, int k) +{ + // empty node + if (!root) + return; + + // add current node to the path + path.push_back(root->data); + + // check if there's any k sum path + // in the left sub-tree. + printKPathUtil(root->left, path, k); + + // check if there's any k sum path + // in the right sub-tree. + printKPathUtil(root->right, path, k); + + // check if there's any k sum path that + // terminates at this node + // Traverse the entire path as + // there can be negative elements too + int f = 0; + for (int j = path.size() - 1; j >= 0; j--) + { + f += path[j]; + + // If path sum is k, print the path + if (f == k) + printVector(path, j); + } + + // Remove the current element from the path + path.pop_back(); +} + +// A wrapper over printKPathUtil() +void printKPath(Node* root, int k) +{ + vector path; + printKPathUtil(root, path, k); +} + +// Driver code +int main() +{ + Node* root = new Node(1); + root->left = new Node(3); + root->left->left = new Node(2); + root->left->right = new Node(1); + root->left->right->left = new Node(1); + root->right = new Node(-1); + root->right->left = new Node(4); + root->right->left->left = new Node(1); + root->right->left->right = new Node(2); + root->right->right = new Node(5); + root->right->right->right = new Node(2); + + int k = 5; + printKPath(root, k); + + return 0; +} diff --git a/CPP/Binary Tree/Reverse level order traversal.cpp b/CPP/Binary Tree/Reverse level order traversal.cpp new file mode 100644 index 0000000..4844508 --- /dev/null +++ b/CPP/Binary Tree/Reverse level order traversal.cpp @@ -0,0 +1,99 @@ +/* + link: https://practice.geeksforgeeks.org/problems/reverse-level-order-traversal/1# + + sol: https://www.geeksforgeeks.org/reverse-level-order-traversal/ +*/ + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + same code as in 1_level_order..... + here just change the level iteration from i=height to 1. +*/ +int height(Node* node) { + if (node == NULL) return 0; + else { + int lHeight = height(node->left); + int rHeight = height(node->right); + + if (lHeight > rHeight) return lHeight + 1; + else return rHeight + 1; + } +} + +void getCurrentLevel(Node* root, int level, vector& ans) { + if (root == NULL) return; + + if (level == 1) ans.push_back(root->data); + else if (level > 1) { + getCurrentLevel(root->left, level - 1, ans); + getCurrentLevel(root->right, level - 1, ans); + } +} + +void levelOrderTraversal(Node* root, vector& ans) { + int h = height(root); + for (int i = h;i >= 1;i--) { + getCurrentLevel(root, i, ans); + } +} + +vector reverseLevelOrder(Node* root) +{ + // code here + vector ans; + levelOrderTraversal(root, ans); + return ans; +} + + + + + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + using queue and stack + + same code as in 1_level_order..... + here just change + 1. push right node first as in reverse we want left node first + 2. after pushing everything in queue, pop it and push to stack (it will make reverse) + +*/ +vector printLevelOrder(Node* root) +{ + // Base Case + if (root == NULL) return; + + // Create an empty queue for level order traversal + queue q; + stack s; + vector ans; + + // Enqueue Root and initialize height + q.push(root); + + while (q.empty() == false) + { + // Print front of queue and remove it from queue + Node* node = q.front(); + + /*Enqueue right child */ + if (node->right != NULL) q.push(node->right); + + /* Enqueue left child */ + if (node->left != NULL) q.push(node->left); + + s.push(node); + q.pop(); + } + while (s.size()) { + ans.push_back(s.top()->data); + s.pop(); + } + return ans; +} \ No newline at end of file diff --git a/CPP/Binary Tree/Right view of tree.cpp b/CPP/Binary Tree/Right view of tree.cpp new file mode 100644 index 0000000..1224cc7 --- /dev/null +++ b/CPP/Binary Tree/Right view of tree.cpp @@ -0,0 +1,122 @@ +/* + link: https://practice.geeksforgeeks.org/problems/right-view-of-binary-tree/1# + + sol: https://www.geeksforgeeks.org/print-right-view-binary-tree-2/ + sol: https://www.geeksforgeeks.org/right-view-binary-tree-using-queue/ +*/ + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + using recursion +*/ +// C++ program to print right view of Binary Tree +#include +using namespace std; + +struct Node +{ + int data; + struct Node* left, * right; +}; + +// A utility function to +// create a new Binary Tree Node +struct Node* newNode(int item) +{ + struct Node* temp = (struct Node*)malloc( + sizeof(struct Node)); + temp->data = item; + temp->left = temp->right = NULL; + return temp; +} + +// Recursive function to print +// right view of a binary tree. +void rightViewUtil(struct Node* root, + int level, int* max_level) +{ + // Base Case + if (root == NULL) return; + + // If this is the last Node of its level + if (*max_level < level) + { + cout << root->data << "\t"; + *max_level = level; + } + + // Recur for right subtree first, + // then left subtree + rightViewUtil(root->right, level + 1, max_level); // main logic (to iterate right sub-tree first) + rightViewUtil(root->left, level + 1, max_level); +} + +// A wrapper over rightViewUtil() +void rightView(struct Node* root) +{ + int max_level = 0; + rightViewUtil(root, 1, &max_level); +} + +// Driver Code +int main() +{ + struct Node* root = newNode(1); + root->left = newNode(2); + root->right = newNode(3); + root->left->left = newNode(4); + root->left->right = newNode(5); + root->right->left = newNode(6); + root->right->right = newNode(7); + root->right->left->right = newNode(8); + + rightView(root); + + return 0; +} + + + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + using queue +*/ +void printRightView(Node* root) +{ + if (!root) return; + + queue q; + q.push(root); + + while (!q.empty()) + { + // number of nodes at current level + int n = q.size(); + + // Traverse all nodes of current level + for (int i = 1; i <= n; i++) + { + Node* temp = q.front(); + q.pop(); + + // Print the right most element + // at the level + if (i == n) + cout << temp->data << " "; + + // Add left node to queue + if (temp->left != NULL) + q.push(temp->left); + + // Add right node to queue + if (temp->right != NULL) + q.push(temp->right); + } + } +} diff --git a/CPP/Binary Tree/Top view of tree.cpp b/CPP/Binary Tree/Top view of tree.cpp new file mode 100644 index 0000000..25a6f92 --- /dev/null +++ b/CPP/Binary Tree/Top view of tree.cpp @@ -0,0 +1,228 @@ +/* + link: https://practice.geeksforgeeks.org/problems/top-view-of-binary-tree/1 + + sol: https://www.geeksforgeeks.org/print-nodes-top-view-binary-tree/ +*/ + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + using level order traversal and hashing. + + here main logic is hd will be derived from parent root and then for children it will be hd-1 and hd+1 + so from there we can know the extreme ends, also in hashing we used heapMap hence will sort according to the + hd value. +*/ +// C++ program to print top +// view of binary tree + +#include +using namespace std; + +// Structure of binary tree +struct Node { + Node* left; + Node* right; + int hd; + int data; +}; + +// function to create a new node +Node* newNode(int key) +{ + Node* node = new Node(); + node->left = node->right = NULL; + node->data = key; + return node; +} + +// function should print the topView of +// the binary tree +void topview(Node* root) +{ + if (root == NULL) + return; + queue q; + map m; + int hd = 0; + root->hd = hd; + + // push node and horizontal distance to queue + q.push(root); + + cout << "The top view of the tree is : \n"; + + while (q.size()) { + hd = root->hd; + + // count function returns 1 if the container + // contains an element whose key is equivalent + // to hd, or returns zero otherwise. + if (m.count(hd) == 0) + m[hd] = root->data; + if (root->left) { + root->left->hd = hd - 1; + q.push(root->left); + } + if (root->right) { + root->right->hd = hd + 1; + q.push(root->right); + } + q.pop(); + root = q.front(); + } + + for (auto i = m.begin(); i != m.end(); i++) { + cout << i->second << " "; + } +} + +// Driver Program to test above functions +int main() +{ + /* Create following Binary Tree + 1 + / \ + 2 3 + \ + 4 + \ + 5 + \ + 6*/ + Node* root = newNode(1); + root->left = newNode(2); + root->right = newNode(3); + root->left->right = newNode(4); + root->left->right->right = newNode(5); + root->left->right->right->right = newNode(6); + cout << "Following are nodes in top view of Binary " + "Tree\n"; + topview(root); + return 0; +} + + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + using map + + Time Complexity of the above implementation is O(nlogn) + where n is the number of nodes in the given binary tree with each insertion operation + in Map requiring O(log2n) complexity. +*/ +// function to fill the map +void fillMap(Node* root, int d, int l, + map >& m) +{ + if (root == NULL) + return; + + // if that extreme end node is not in our map + if (m.count(d) == 0) { + m[d] = make_pair(root->data, l); + } + // if extreme node is there but as it is overlapped by less order level, we have to replace it. + else if (m[d].second > l) { + m[d] = make_pair(root->data, l); + } + + fillMap(root->left, d - 1, l + 1, m); + fillMap(root->right, d + 1, l + 1, m); +} + +// function should print the topView of +// the binary tree +void topView(struct Node* root) +{ + + // map to store the pair of node value and its level + // with respect to the vertical distance from root. + map > m; + + // fillmap(root,vectical_distance_from_root,level_of_node,map) + fillMap(root, 0, 0, m); + + for (auto it = m.begin(); it != m.end(); it++) { + cout << it->second.first << " "; + } +} + + + + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + using queue and stack +*/ +void topView() +{ + // queue for holding nodes and their horizontal + // distance from the root node + queue > q; + + // pushing root node with distance 0 + q.push(make_pair(root, 0)); + + // hd is currect node's horizontal distance from + // root node l is currect left min horizontal + // distance (or max in magnitude) so far from the + // root node r is currect right max horizontal + // distance so far from the root node + + int hd = 0, l = 0, r = 0; + + // stack is for holding left node's data because + // they will appear in reverse order that is why + // using stack + stack left; + + // vector is for holding right node's data + vector right; + + Node* node; + + while (q.size()) { + + node = q.front().first; + hd = q.front().second; + + if (hd < l) { + left.push(node->data); + l = hd; + } + else if (hd > r) { + right.push_back(node->data); + r = hd; + } + + if (node->left) { + q.push(make_pair(node->left, hd - 1)); + } + if (node->right) { + q.push(make_pair(node->right, hd + 1)); + } + + q.pop(); + } + // printing the left node's data in reverse order + while (left.size()) { + cout << left.top() << " "; + left.pop(); + } + + // then printing the root node's data + cout << root->data << " "; + + // finally printing the right node's data + for (auto x : right) { + cout << x << " "; + } +} diff --git a/CPP/Binary Tree/Trees isomorphism problem.cpp b/CPP/Binary Tree/Trees isomorphism problem.cpp new file mode 100644 index 0000000..c6a29d8 --- /dev/null +++ b/CPP/Binary Tree/Trees isomorphism problem.cpp @@ -0,0 +1,91 @@ +/* + link: https://practice.geeksforgeeks.org/problems/check-if-tree-is-isomorphic/1 + + sol: https://www.geeksforgeeks.org/tree-isomorphism-problem/ +*/ + + + +// ----------------------------------------------------------------------------------------------------------------------- // +/* + Time Complexity: + The above solution does a traversal of both trees. + So time complexity is O(min(m,n)*2) or O(min(m,n)) where m and n are number of nodes in given trees. +*/ + +// A C++ program to check if two given trees are isomorphic +#include +using namespace std; + +/* A binary tree node has data, pointer to left and right children */ +struct node +{ + int data; + struct node* left; + struct node* right; +}; + +/* Given a binary tree, print its nodes in reverse level order */ +bool isIsomorphic(node* n1, node* n2) +{ +// Both roots are NULL, trees isomorphic by definition + if (n1 == NULL && n2 == NULL) + return true; + + // Exactly one of the n1 and n2 is NULL, trees not isomorphic + if (n1 == NULL || n2 == NULL) + return false; + + if (n1->data != n2->data) + return false; + + // There are two possible cases for n1 and n2 to be isomorphic + // Case 1: The subtrees rooted at these nodes have NOT been "Flipped". + // Both of these subtrees have to be isomorphic, hence the && + // Case 2: The subtrees rooted at these nodes have been "Flipped" + return + (isIsomorphic(n1->left, n2->left) && isIsomorphic(n1->right, n2->right)) || + (isIsomorphic(n1->left, n2->right) && isIsomorphic(n1->right, n2->left)); +} + +/* Helper function that allocates a new node with the +given data and NULL left and right pointers. */ +node* newNode(int data) +{ + node* temp = new node; + temp->data = data; + temp->left = NULL; + temp->right = NULL; + + return (temp); +} + +/* Driver program to test above functions*/ +int main() +{ + // Let us create trees shown in above diagram + struct node* n1 = newNode(1); + n1->left = newNode(2); + n1->right = newNode(3); + n1->left->left = newNode(4); + n1->left->right = newNode(5); + n1->right->left = newNode(6); + n1->left->right->left = newNode(7); + n1->left->right->right = newNode(8); + + struct node* n2 = newNode(1); + n2->left = newNode(3); + n2->right = newNode(2); + n2->right->left = newNode(4); + n2->right->right = newNode(5); + n2->left->right = newNode(6); + n2->right->right->left = newNode(8); + n2->right->right->right = newNode(7); + + if (isIsomorphic(n1, n2) == true) + cout << "Yes"; + else + cout << "No"; + + return 0; +} From e2d08be7a6788f828989c83a1bbc269695508f65 Mon Sep 17 00:00:00 2001 From: Akash Gautam <76935019+geekblower@users.noreply.github.com> Date: Thu, 20 Oct 2022 09:45:26 +0530 Subject: [PATCH 3/4] Add files via upload --- CPP/Array/Union and intersection.cpp | 34 ++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 CPP/Array/Union and intersection.cpp diff --git a/CPP/Array/Union and intersection.cpp b/CPP/Array/Union and intersection.cpp new file mode 100644 index 0000000..9a1510f --- /dev/null +++ b/CPP/Array/Union and intersection.cpp @@ -0,0 +1,34 @@ +/* + link: https://practice.geeksforgeeks.org/problems/union-of-two-arrays3538/1 + + sol: https://www.geeksforgeeks.org/find-union-and-intersection-of-two-unsorted-arrays/ + for different approach +*/ + + +// ----------------------------------------------------------------------------------------------------------------------- // +int doUnion(int a[], int n, int b[], int m) { + set s; + for (int i = 0;i < n;i++) s.insert(a[i]); + for (int i = 0;i < m;i++) s.insert(b[i]); + return s.size(); +} + +int doIntersection(int a[], int n, int b[], int m) { + sort(a, a + n); + sort(b, b + m); + + int i = 0, j = 0, ans = 0; + + while (i <= j) { + if (a[i] == b[j]) { + ans++; + i++; + j++; + } + else if (a[i] < b[j]) i++; + else j++; + } + return ans; +} + From 58fcb41b70544338ad0c1e0b5fae8b673518f4bf Mon Sep 17 00:00:00 2001 From: Akash Gautam <76935019+geekblower@users.noreply.github.com> Date: Thu, 20 Oct 2022 09:46:17 +0530 Subject: [PATCH 4/4] Dynamic Programming problems in C++ --- CPP/Dynamic Programming/0-1 knapsack.cpp | 95 +++++++++++++++ .../Binomial cofficient.cpp | 108 ++++++++++++++++++ CPP/Dynamic Programming/Coin change.cpp | 26 +++++ CPP/Dynamic Programming/Equal subset sum.cpp | 49 ++++++++ CPP/Dynamic Programming/LC subsequences.cpp | 33 ++++++ CPP/Dynamic Programming/LC substring.cpp | 33 ++++++ .../Longest palindromic subsequence.cpp | 20 ++++ .../Longest repeated subsequence.cpp | 36 ++++++ ...on in a string to make it a palindrome.cpp | 20 ++++ .../Permutation coefficient problem.cpp | 24 ++++ 10 files changed, 444 insertions(+) create mode 100644 CPP/Dynamic Programming/0-1 knapsack.cpp create mode 100644 CPP/Dynamic Programming/Binomial cofficient.cpp create mode 100644 CPP/Dynamic Programming/Coin change.cpp create mode 100644 CPP/Dynamic Programming/Equal subset sum.cpp create mode 100644 CPP/Dynamic Programming/LC subsequences.cpp create mode 100644 CPP/Dynamic Programming/LC substring.cpp create mode 100644 CPP/Dynamic Programming/Longest palindromic subsequence.cpp create mode 100644 CPP/Dynamic Programming/Longest repeated subsequence.cpp create mode 100644 CPP/Dynamic Programming/Minimum number of deletion in a string to make it a palindrome.cpp create mode 100644 CPP/Dynamic Programming/Permutation coefficient problem.cpp diff --git a/CPP/Dynamic Programming/0-1 knapsack.cpp b/CPP/Dynamic Programming/0-1 knapsack.cpp new file mode 100644 index 0000000..d2e0d0e --- /dev/null +++ b/CPP/Dynamic Programming/0-1 knapsack.cpp @@ -0,0 +1,95 @@ +/* + link: https://practice.geeksforgeeks.org/problems/0-1-knapsack-problem0945/1 +*/ + +// ----------------------------------------------------------------------------------------------------------------------- // + +// memoization with global +int static memo[1001][1001]; +int recur(int w, int wt[], int val[], int n) { + if (n == 0 || w == 0) return 0; + if (memo[n][w] != -1) return memo[n][w]; + if (wt[n - 1] <= w) { + return memo[n][w] = max(val[n - 1] + recur(w - wt[n - 1], wt, val, n - 1), recur(w, wt, val, n - 1)); + } + else if (wt[n - 1] > w) { + return memo[n][w] = recur(w, wt, val, n - 1); + } +} +int knapSack(int w, int wt[], int val[], int n) +{ + memset(memo, -1, sizeof(memo)); + recur(w, wt, val, n); + return memo[n][w]; +} + +// ----------------------------------------------------------------------------------------------------------------------- // + +// memoization with global (another way, code is just same as above) +vector> memo; +int recur(int w, int wt[], int val[], int n) { + if (n == 0 || w == 0) return 0; + if (memo[n][w] != -1) return memo[n][w]; + if (wt[n - 1] <= w) { + return memo[n][w] = max(val[n - 1] + recur(w - wt[n - 1], wt, val, n - 1), recur(w, wt, val, n - 1)); + } + else if (wt[n - 1] > w) { + return memo[n][w] = recur(w, wt, val, n - 1); + } +} +int knapSack(int w, int wt[], int val[], int n) +{ + memo = vector>(n + 1, vector(w + 1, -1)); + + return recur(w, wt, val, n); +} + +// ----------------------------------------------------------------------------------------------------------------------- // + +// memoization (another way, code is just same as above) +int recur(int w, int wt[], int val[], int n, vector>& memo) { + if (n == 0 || w == 0) return 0; + if (memo[n][w] != -1) return memo[n][w]; + if (wt[n - 1] <= w) { + return memo[n][w] = max(val[n - 1] + recur(w - wt[n - 1], wt, val, n - 1, memo), recur(w, wt, val, n - 1, memo)); + } + else if (wt[n - 1] > w) { + return memo[n][w] = recur(w, wt, val, n - 1, memo); + } +} +int knapSack(int w, int wt[], int val[], int n) +{ + vector> memo; + memo.resize(n + 1, vector(w + 1, -1)); + + return recur(w, wt, val, n, memo); +} + +// ----------------------------------------------------------------------------------------------------------------------- // + +// tabulation +int knapSack(int w, int wt[], int val[], int n) +{ + vector> memo; + memo.resize(n + 1, vector(w + 1, -1)); + for (int i = 0;i < n + 1;i++) { + memo[i][0] = 0; + } + for (int j = 0;j < w + 1;j++) { + memo[0][j] = 0; + } + + for (int i = 1;i < n + 1;i++) { + for (int j = 1;j < w + 1;j++) { + if (wt[i - 1] <= j) { + memo[i][j] = max(val[i - 1] + memo[i - 1][j - wt[i - 1]], memo[i - 1][j]); + } + else { + memo[i][j] = memo[i - 1][j]; + } + } + } + return memo[n][w]; +} + +// ----------------------------------------------------------------------------------------------------------------------- // \ No newline at end of file diff --git a/CPP/Dynamic Programming/Binomial cofficient.cpp b/CPP/Dynamic Programming/Binomial cofficient.cpp new file mode 100644 index 0000000..823c55a --- /dev/null +++ b/CPP/Dynamic Programming/Binomial cofficient.cpp @@ -0,0 +1,108 @@ +/* + link: https://practice.geeksforgeeks.org/problems/ncr1019/1# + + n C r= (n-1 C r) + (n-1 C r-1) + thread to understand above equation: https://discuss.codechef.com/t/need-some-explanation-on-the-combinatorics-formula-ncr-n-1cr-n-1cr-1/13834 +*/ + +// ----------------------------------------------------------------------------------------------------------------------- // + +// recursion +// let's assume if n is the whole class and r is to select few student +int recur(int n, int r) { + // base condition + if (r == 0 || r == n) return 1; + if (n < r) return 0; + + return recur(n - 1, r - 1) + recur(n - 1, r); + /* + recur(n-1, r-1): it says select favourite student hence total-1 and student_still_left_to_select - 1 ; + recur(n-1, r): it means reject that favourite student hence total-1 and student_still_left_to_select remains same. + */ +} +int nCr(int n, int r) { + return recur(n, r); +} + +// ----------------------------------------------------------------------------------------------------------------------- // + +// memoization +long long memo[1001][1001]; +const long long mod = 1e9 + 7; +int recur(int n, int r) { + // base condition + if (r == 0 || r == n) return 1; + if (n < r) return 0; + if (memo[n][r] != -1) return memo[n][r]; + + return memo[n][r] = ((recur(n - 1, r - 1) % mod) + (recur(n - 1, r) % mod) % mod); +} +int nCr(int n, int r) { + memset(memo, -1, sizeof(memo)); + return recur(n, r) % mod; +} + + +// ----------------------------------------------------------------------------------------------------------------------- // + +// tabulation +const long long mod = 1e9 + 7; +int memo[1001][1001]; +int nCr(int n, int r) { + if (n < r) return 0; + + // base condition + + for (int j = 0;j < r + 1;j++) { + memo[0][j] = 0; + } + for (int i = 0;i < n + 1;i++) { + memo[i][0] = 1; + } + + for (int i = 1;i < n + 1;i++) { + for (int j = 1;j <= min(i, r);j++) { + memo[i][j] = (memo[i - 1][j - 1] % mod + memo[i - 1][j] % mod) % mod; + } + } + return memo[n][r] % mod; +} + +// ----------------------------------------------------------------------------------------------------------------------- // + +// another tabulation (bit confusing so u can avoid it..) +long long nCr(int n, int r) { + // code here + const long long mod = 1e9 + 7; + vector v(r + 1, 0); + v[0] = 1; + for (int i = 1;i <= n;i++) { + for (int j = min(r, i); j > 0;j--) { + v[j] = (v[j] + v[j - 1]) % mod; + } + } + return v[r]; +} + +// ----------------------------------------------------------------------------------------------------------------------- // + +// MOST OPTIMIZED VERSION +// TC: O(N) + +/* + use pen paper and put value like 5C2 to understand + nCk = [n*(n-1)*---*(n-k+1)] / [k*(k-1)*---*1] +*/ +long long nCr(int n, int r) { + long long int ans = 1; + + if (r > n - r) r = n - r; + + for (int i = 0;i < r;i++) { + ans *= (n - i); + ans /= (i + 1); + } + return ans; +} + +// ----------------------------------------------------------------------------------------------------------------------- // \ No newline at end of file diff --git a/CPP/Dynamic Programming/Coin change.cpp b/CPP/Dynamic Programming/Coin change.cpp new file mode 100644 index 0000000..ac9bca7 --- /dev/null +++ b/CPP/Dynamic Programming/Coin change.cpp @@ -0,0 +1,26 @@ +/* + link: https://practice.geeksforgeeks.org/problems/coin-change2448/1 + + variation of unbounded_knapsack for more refer to DP_tut/unbounded_knapsack/3_coin.... +*/ + +// ----------------------------------------------------------------------------------------------------------------------- // + +long long int count(int coins[], int n, int sum) +{ + vector> memo(n + 1, vector(sum + 1)); + for (int j = 0;j < sum + 1;j++) memo[0][j] = 0; + for (int i = 1;i < n + 1;i++) memo[i][0] = 1; + + for (int i = 1;i < n + 1;i++) { + for (int j = 1;j < sum + 1;j++) { + if (coins[i - 1] <= j) { + memo[i][j] = memo[i][j - coins[i - 1]] + memo[i - 1][j]; + } + else memo[i][j] = memo[i - 1][j]; + } + } + return memo[n][sum]; +} + +// ----------------------------------------------------------------------------------------------------------------------- // \ No newline at end of file diff --git a/CPP/Dynamic Programming/Equal subset sum.cpp b/CPP/Dynamic Programming/Equal subset sum.cpp new file mode 100644 index 0000000..a00511f --- /dev/null +++ b/CPP/Dynamic Programming/Equal subset sum.cpp @@ -0,0 +1,49 @@ +/* + link: https://practice.geeksforgeeks.org/problems/subset-sum-problem2014/1 + + for memoization go to DP_tut/1_0-1_knapsack/2_subset... its just variation +*/ + +// ----------------------------------------------------------------------------------------------------------------------- // + +// tabulation +class Solution { +public: + bool subsetSum(int arr[], int n, int sum) { + vector> tabu(n + 1, vector(sum + 1)); + for (int i = 0;i < n + 1;i++) { + tabu[i][0] = true; + } + for (int j = 1;j < sum + 1;j++) { + tabu[0][j] = false; + } + + for (int i = 1;i < n + 1;i++) { + for (int j = 1;j < sum + 1;j++) { + if (arr[i - 1] <= j) { + tabu[i][j] = tabu[i - 1][j - arr[i - 1]] || tabu[i - 1][j]; + } + else tabu[i][j] = tabu[i - 1][j]; + } + } + return tabu[n][sum]; + } + int equalPartition(int N, int arr[]) + { + int sum = 0; + for (int i = 0;i < N;i++) { + sum += arr[i]; + } + + // this is crux of whole problem + // if sum found is odd then its not possible to divide the array in 2 subset + // and if sum found is even then we can use subset sum problem/implemetation to complete rest of the problem. + if (sum % 2) return 0; + sum /= 2; + + return subsetSum(arr, N, sum); + } + +}; + +// ----------------------------------------------------------------------------------------------------------------------- // \ No newline at end of file diff --git a/CPP/Dynamic Programming/LC subsequences.cpp b/CPP/Dynamic Programming/LC subsequences.cpp new file mode 100644 index 0000000..2ac3531 --- /dev/null +++ b/CPP/Dynamic Programming/LC subsequences.cpp @@ -0,0 +1,33 @@ +/* + link: https://practice.geeksforgeeks.org/problems/longest-common-subsequence-1587115620/1 + + refer DP_tut/LCS/implementation +*/ + +// ----------------------------------------------------------------------------------------------------------------------- // + +// function to find longest common subsequence +int static memo[1001][1001]; +int lcs(int n, int m, string s1, string s2) { + + // your code here + for (int i = 0;i < n + 1;i++) { + memo[i][0] = 0; + } + for (int j = 0;j < m + 1;j++) { + memo[0][j] = 0; + } + for (int i = 1;i < n + 1;i++) { + for (int j = 1;j < m + 1;j++) { + if (s1[i - 1] == s2[j - 1]) { + memo[i][j] = 1 + memo[i - 1][j - 1]; + } + else { + memo[i][j] = max(memo[i - 1][j], memo[i][j - 1]); + } + } + } + return memo[n][m]; +} + +// ----------------------------------------------------------------------------------------------------------------------- // \ No newline at end of file diff --git a/CPP/Dynamic Programming/LC substring.cpp b/CPP/Dynamic Programming/LC substring.cpp new file mode 100644 index 0000000..5ad02cc --- /dev/null +++ b/CPP/Dynamic Programming/LC substring.cpp @@ -0,0 +1,33 @@ +/* + link: https://practice.geeksforgeeks.org/problems/longest-common-substring1452/1 + + variation of DP_tut/LCS/2_LC_substring... +*/ + +// ----------------------------------------------------------------------------------------------------------------------- // + +int memo[1001][1001]; + +int longestCommonSubstr(string s1, string s2, int n, int m) +{ + // memset(memo, -1, sizeof(memo)); + // your code here + int result = 0; + for (int i = 0;i < n + 1;i++) memo[i][0] = 0; + for (int j = 0;j < m + 1;j++) memo[0][j] = 0; + + for (int i = 1;i < n + 1;i++) { + for (int j = 1;j < m + 1;j++) { + if (s1[i - 1] == s2[j - 1]) { + memo[i][j] = 1 + memo[i - 1][j - 1]; + result = max(result, memo[i][j]); + } + else { + memo[i][j] = 0; + } + } + } + return result; +} + +// ----------------------------------------------------------------------------------------------------------------------- // \ No newline at end of file diff --git a/CPP/Dynamic Programming/Longest palindromic subsequence.cpp b/CPP/Dynamic Programming/Longest palindromic subsequence.cpp new file mode 100644 index 0000000..42bfb0e --- /dev/null +++ b/CPP/Dynamic Programming/Longest palindromic subsequence.cpp @@ -0,0 +1,20 @@ +/* + + link: https://www.geeksforgeeks.org/longest-palindromic-subsequence-dp-12/ + + problem: given a string find longest palindromic subsequence + output: length of longest palindromic subsequence + + refer DP_tut\3_LCS\6_Longest_Palindromic... + + crux of the problem: if we want to find the subsequence we use LCS + then if want to find the palindromic then use the same string and reverse it. + +*/ + +// ----------------------------------------------------------------------------------------------------------------------- // + +int main() { + // string s2 = reverse of s1. + return LCS(s1, s2, n, n); +} \ No newline at end of file diff --git a/CPP/Dynamic Programming/Longest repeated subsequence.cpp b/CPP/Dynamic Programming/Longest repeated subsequence.cpp new file mode 100644 index 0000000..32357ed --- /dev/null +++ b/CPP/Dynamic Programming/Longest repeated subsequence.cpp @@ -0,0 +1,36 @@ +/* + link: https://practice.geeksforgeeks.org/problems/longest-repeating-subsequence2004/1 + + variation of LCS. +*/ + +// ----------------------------------------------------------------------------------------------------------------------- // + +class Solution { + int memo[1001][1001]; +public: + int LCS(string s1, string s2, int n, int m) + { + for (int i = 0;i < n + 1;i++) memo[i][0] = 0; + for (int j = 0;j < m + 1;j++) memo[0][j] = 0; + + for (int i = 1;i < n + 1;i++) { + for (int j = 1;j < m + 1;j++) { + if (s1[i - 1] == s2[j - 1] && i != j) { // crux: add only if position are not same and char is same. + memo[i][j] = 1 + memo[i - 1][j - 1]; + } + else { + memo[i][j] = max(memo[i - 1][j], memo[i][j - 1]); + } + } + } + return memo[n][m]; + } + int LongestRepeatingSubsequence(string str) { + // Code here + return LCS(str, str, str.length(), str.length()); + } + +}; + +// ----------------------------------------------------------------------------------------------------------------------- // \ No newline at end of file diff --git a/CPP/Dynamic Programming/Minimum number of deletion in a string to make it a palindrome.cpp b/CPP/Dynamic Programming/Minimum number of deletion in a string to make it a palindrome.cpp new file mode 100644 index 0000000..72ea8b8 --- /dev/null +++ b/CPP/Dynamic Programming/Minimum number of deletion in a string to make it a palindrome.cpp @@ -0,0 +1,20 @@ +/* + link: https://www.geeksforgeeks.org/minimum-number-deletions-make-string-palindrome/ + + problem: given string find min. no. of deletion to make it palindrom. + output: min. no. of operation + + crux: find subsequence with palindromic of string itself, and then subtract with the length + refer: longest palindromic subsequnce. + + variation of LCS +*/ + +// ----------------------------------------------------------------------------------------------------------------------- // + +int main() { + // string s2 = reverse of s1. + return s1.length() - LCS(s1, s2, n, n); +} + +// ----------------------------------------------------------------------------------------------------------------------- // \ No newline at end of file diff --git a/CPP/Dynamic Programming/Permutation coefficient problem.cpp b/CPP/Dynamic Programming/Permutation coefficient problem.cpp new file mode 100644 index 0000000..fd105e7 --- /dev/null +++ b/CPP/Dynamic Programming/Permutation coefficient problem.cpp @@ -0,0 +1,24 @@ +/* + link: https://www.geeksforgeeks.org/permutation-coefficient/ + + logic is same as 9_binomial_cofficient but here it is permutation +*/ + +// ----------------------------------------------------------------------------------------------------------------------- // + +// recursion +// let's assume if n is the no. of balls and r is to position to fill +int recur(int n, int r) { + // base condition + if (n < r) return 0; + if (n == 0 || r == 0) return 1; + + return recur(n - 1, r) + (r * recur(n - 1, r - 1)); + /* recur(n-1, r-1): it says select fixed ball hence total-1 and ball_left_to_select - 1 and now also there are r pos to permute that fixed ball. + recur(n-1, r): it means reject that fixed ball hence total-1 and ball_left_to_select remains same. + */ +} + +// do memoization and tabulation by self. + +// ----------------------------------------------------------------------------------------------------------------------- // \ No newline at end of file