diff --git a/LeetCode/Algorithms/CountSubsetsWithSumK.cpp b/LeetCode/Algorithms/CountSubsetsWithSumK.cpp new file mode 100644 index 0000000..8e43621 --- /dev/null +++ b/LeetCode/Algorithms/CountSubsetsWithSumK.cpp @@ -0,0 +1,32 @@ +int mod = (int)(1e9 + 7); +int f(vector &arr, int ind, int sum, vector> &dp) { + // if(sum == 0) return 1; + if(ind == 0) { + if(sum == 0 && arr[0] == 0) return 2; // 0 0 1 2 3, target = 5 - to handle case where multiple 0's + if(sum == 0) return 1; // + return arr[0] == sum; + // if(sum == 0 || sum == arr[0]) return 1; + // return 0; + } + if(dp[ind][sum] != -1) return dp[ind][sum]; + // not take + int notTake = f(arr, ind - 1, sum, dp); + + // take + int take = 0; + if(sum >= arr[ind]) { + take = f(arr, ind -1, sum - arr[ind], dp); + } + + return dp[ind][sum] = (take + notTake) % mod; +} + +int findWays(vector& arr, int k) +{ + // Write your code here. + int n = arr.size(); + vector> dp(n, vector(k + 1, -1)); + return f(arr, n-1, k, dp); +} + + diff --git a/LeetCode/Algorithms/DisjoinSet.cpp b/LeetCode/Algorithms/DisjoinSet.cpp new file mode 100644 index 0000000..e55db19 --- /dev/null +++ b/LeetCode/Algorithms/DisjoinSet.cpp @@ -0,0 +1,78 @@ +#include +using namespace std; +class DisjoinSet { + vector rank, parent, size; + +public: + DisjoinSet(int n) { + rank.resize(n + 1, 0); + size.resize(n + 1, 0); + parent.resize(n + 1); + for(int i=0; i<=n; i++) { + parent[i] = i; + size[i] = 1; + } + } + + int findUPar(int node) { + if(node == parent[node]) { + return node; + } + return parent[node] = findUPar(parent[node]); + } + + void UnionByRank(int u, int v) { + int ulp_u = findUPar(u); + int ulp_v = findUPar(v); + + if(ulp_u == ulp_v) { + return; + } else if(rank[ulp_v] > rank[ulp_u]) { + parent[ulp_u] = ulp_v; + } else if(rank[ulp_u] > rank[ulp_v]) { + parent[ulp_v] = ulp_u; + } else if(rank[ulp_u] == rank[ulp_v]) { + parent[ulp_v] = ulp_u; + rank[ulp_v]++; + } + } + + void UnionBySize(int u, int v) { + int ulp_u = parent[u]; + int ulp_v = parent[v]; + + if(ulp_u == ulp_v) return; + if(size[ulp_u] > size[ulp_v]) { + size[ulp_u] += size[ulp_v]; + parent[ulp_v] = ulp_u; + } else { + size[ulp_v] += size[ulp_u]; + parent[ulp_u] = ulp_v; + } + } +}; + +int main() { + DisjoinSet ds(7); + ds.UnionByRank(1, 2); + ds.UnionByRank(2, 3); + ds.UnionByRank(4, 5); + ds.UnionByRank(6, 7); + ds.UnionByRank(5, 6); + // ds.UnionByRank(1, 2); + + // if 3 and 7 same or not + if(ds.findUPar(3) == ds.findUPar(7)) { + cout<<"Same"<start = start; + * this->end = end; + * } + * } + */ + +class Solution { +public: + // struct myComp { + // bool operator() (Interval &a, Interval &b) { + // return a.start < b.start; + // } + // }; + + static bool myComp(const Interval &a, const Interval &b) { + return a.start < b.start; + } + + bool canAttendMeetings(vector& intervals) { + if(intervals.empty()) return true; + sort(intervals.begin(), intervals.end(), myComp); + + // sort(intervals.begin(), intervals.end(), myComp()); + + // sort(intervals.begin(), intervals.end(), [](Interval &a, Interval &b) { + // return a.start < b.start; + // }); + + int prevEnd = intervals[0].end; + + for(int i=1; i& nums, long long k) { + ll left = 0, right = 0; // window is [left, right) + ll sum = 0; // sum of nums[left ... right -1] + ll count = 0; + + ll n = nums.size(); + + while(left < n) { + // find larget valid window + while(right < n && (sum + nums[right] * (right - left + 1) < k)) { + sum += nums[right]; + right++; + } + + // All subarrays starting at 'left' and ending before 'right' are valid + count += right - left; + + // Slide the window forward by removing nums[left] + // If we couldn't even include nums[left], move both pointer past it + if(left == right) { + right++; + } else { + sum -= nums[left]; + } + + left++; + } + + return count; + } +}; + +/* + +Time Complexity - O(N) +Space Complexity - O(1) + +Counting Logic + 0 1 2 3 4 5 +a[]: [2, 1, 1, 3, 4, 1], k = 15 + | | + start end + +1. Increase end till sum * len < k +2. Count = end - start +3. Increase start pointer and again when sum * len >= k, + calculate count and increment start++ pointer + +[start, End) => largest subarray starting at '0' which has (sum * size) < k + +start, end - 1 ie 4 * 3 < 15 + +Count of such Subarrays start at '0' = 3 + +in general [start, start], [start, start+ 1], ... [start, end-1] + +count = end - start + +// Two Pointer + Sliding Window + + + +*/ \ No newline at end of file diff --git a/LeetCode/Algorithms/Hard/FindMinimumDiameterAfterMergingTwoTrees.cpp b/LeetCode/Algorithms/Hard/FindMinimumDiameterAfterMergingTwoTrees.cpp new file mode 100644 index 0000000..35504e9 --- /dev/null +++ b/LeetCode/Algorithms/Hard/FindMinimumDiameterAfterMergingTwoTrees.cpp @@ -0,0 +1,111 @@ +class Solution { +public: + int diameter(unordered_map>& adj, int n) { + // pick any node and find the farthest from that node + vector visited(n, false); + queue q; + q.push(0); + visited[0] = true; + int last; + while(!q.empty()) { + int size = q.size(); + for(int i=0; i vis(n, false); + vis[last] = true; + while(!q.empty()) { + int size = q.size(); + for(int i=0; i>& edges) { + if(edges.size() == 0) { + return 0; + } + + unordered_map> adj; + unordered_set nodes; + + for(auto &edge: edges) { + cout<>& edges1, vector>& edges2) { + int dia1 = findDiameter(edges1); + int dia2 = findDiameter(edges2); + + int radius1 = (dia1 + 1) / 2; + int radius2 = (dia2 + 1) / 2; + int sum = 1 + radius1 + radius2; + + return max(sum, max(dia1, dia2)); + } +}; + +// Time Complexity - O(N + M) +// Space Complexity - O(N + M) + +// Follow-up +// 1. Prove the greedy algo. +// 2. Find al diameters of a tree + +// How to find optimal path? + +// Note: It is always optimal to join at midpoint of diameter + +// total height = h1 / 2 + bridge (1) + h2 / 2 + +// Cases + +// Even-Even ==> ans = 1 + dia1 / 2 + dia2 / 2 +// Odd-Even ==> ans = 1 + (dia1 + 1) / 2 + dia2 / 2 +// Odd-Odd ==> ans = 1 + (dia1 + 1) / 2 + (dia2 + 1) / 2 + +// How to find diameter of undirected tree? +// Greedy Algorithm +// 1. Choose any node (a) +// 2. Find farthest node from a (b) --> BFS(levelorder) +// 3. Find farthest node from b and count no. of hops / levels +// diameter = no. of hops + +// Case 1: Your chosen node is already on diameter + +// Joining may not always contain diameter + +// max diameter = max{dia1, dia2, 1 + (dia1 + 1) / 2 + (dia2 + 1) / 2} + + diff --git a/LeetCode/Algorithms/Hard/LargestRectangleInHistogram.cpp b/LeetCode/Algorithms/Hard/LargestRectangleInHistogram.cpp new file mode 100644 index 0000000..7149fcf --- /dev/null +++ b/LeetCode/Algorithms/Hard/LargestRectangleInHistogram.cpp @@ -0,0 +1,42 @@ +class Solution { +public: + int largestRectangleArea(vector& heights) { + int maxArea = 0; + stack> stk; // (index, height) + int n = heights.size(); + for(int i=0; i heights[i]) { + auto temp = stk.top(); + stk.pop(); + + int index = temp.first; + int height = temp.second; + maxArea = max(maxArea, height * (i - index)); + start = index; + } + + stk.push({start, heights[i]}); + } + + // calculate the area of the remaining elements + // in stack, area to be calcualted by condering from + // length of height array + while(!stk.empty()) { + auto temp = stk.top(); + stk.pop(); + + int index = temp.first; + int height = temp.second; + + maxArea = max(maxArea, height * (n - index)); + } + return maxArea; + } +}; + +// Time Complexity - O(N) +// Space Complexity - O(N) \ No newline at end of file diff --git a/LeetCode/Algorithms/Hard/MaximumNumberOfTasksYouCanAssign.cpp b/LeetCode/Algorithms/Hard/MaximumNumberOfTasksYouCanAssign.cpp new file mode 100644 index 0000000..616b7fe --- /dev/null +++ b/LeetCode/Algorithms/Hard/MaximumNumberOfTasksYouCanAssign.cpp @@ -0,0 +1,156 @@ +class Solution { + public: + bool canAssign(int mid, vector &workers, vector &tasks, int pills, int strength) { + // it means that if mid = 2, we'll be taking the last two values in workers and putting them in multiset + multiset usable_workers(workers.end() - mid, workers.end()); + + // iterating from right to left + for(int i=mid-1; i>=0; i--) { + auto curr_workers = --usable_workers.end(); + + if(*curr_workers < tasks[i]) { + if(pills <= 0) return false; + + // Optimal Strategy: Assign weakest worker to get the current task done + auto weakest_worker = usable_workers.lower_bound(tasks[i] - strength); + + if(weakest_worker == usable_workers.end()) { + return false; // no one can be assigned the current job (even using pill) + } + + pills--; + usable_workers.erase(weakest_worker); + } else { + usable_workers.erase(curr_workers); + } + } + return true; + } + + int maxTaskAssign(vector& tasks, vector& workers, int pills, int strength) { + sort(workers.begin(), workers.end()); + sort(tasks.begin(), tasks.end()); + + int low = 0; + int high = min(tasks.size(), workers.size()); + int mid; + + int assigned = 0; + while(low <= high) { + mid = low + (high - low) / 2; + + if(canAssign(mid, workers, tasks, pills, strength)) { + assigned = mid; + low = mid + 1; + } else { + high = mid - 1; + } + } + + return assigned; + } +}; + +/* +Optimal Matchup Strategy + +Strategy - 1: Strong fights the weak + +Strategy - 2: Strong fights strong. (fair) -- choose this one + +Ques: What if you have G > R or G < R + +Note: Sort to search optimal matchups faster + +Goal: Get more wins for green + +Note: +Fights are only 1:1 +A person can only fight once + +1 7 6 +2 6 5 + +Sorting: + +1. Remove the person who is the strongest in the opposite team + + +I. +II. 2, (4, 5, 6) -> (N - M) workers ignore + +Sorted Asc: Strongest worker gets hardest job + 0 1 2 +T[]: [6, 7, 7] , Pill = 1, Strength = 3 +W[]: [2, 5, 6] + +Lower bound binary search: + + 0 1 2 3 4 5 6 7 +[1, 2, 2, 4, 4, 5, 7, 7] + +lb(2) = 1 +lb(6) = 6 + +// set shoudl not be used because the order is not unique + +multiset works well in this scenario since it preserves order +or +ordered_map + +Max tasks to be done <= Max workers + + 0 1 2 3 4 +T[] : [7, 6, 8, 7, 9] => T[]: [6, 7, 7, 8, 9] + <---- | ignore + 0 1 2 0 1 2 +W[] : [6, 2, 5] => W[]: [2, 5, 6] + +Strategy: Choose weakest M tasks + +If N < M then only N workers + + 0 1 +T[]: [6, 7] --> N + + 0 1 2 +W[]: [2, 5, 6] --> M +ignore| + +M > N + +Note: R->L is imp to match strongest W[i] with toughest task + +Max No of Tasks: Similar to Leetcode's First Bad version probelm + +Goal: Find max tasks which can be done +-> find the first bad version + +low = 0 +high = min(N, M) +mid = low + (high - low) / 2 + +if(canAssign(mid)) { + assigned = mid; + love = mid + 1; +} else { + love = mid - 1; +} + +pick strongest worker and weakest task, so that we have change of completing the task + +Time Complexity - + +W = min(N, M) + +logW * W * logW += W(logW)**2 + +Binary Search ---> Loop ---> lower bound on multiset + + +Total time Complexity - W(logW)^2 + NlogN + MlogM, tasks and workers array will also be sorted +Space Complexity - O(W), due to multiset / map being used + +W = min(N, M) +*/ \ No newline at end of file diff --git a/LeetCode/Algorithms/Hard/MaximumSumOf3NonOverlappingSubarrays.cpp b/LeetCode/Algorithms/Hard/MaximumSumOf3NonOverlappingSubarrays.cpp new file mode 100644 index 0000000..09dcad5 --- /dev/null +++ b/LeetCode/Algorithms/Hard/MaximumSumOf3NonOverlappingSubarrays.cpp @@ -0,0 +1,100 @@ +class Solution { +public: + vector prefix_sum; + int max_sum; + int mem[20001][3]; // [pos][count] + + int findMaxSum(vector &nums, int pos, int count, int &k) { + if(count == 3) return 0; // done case + if(pos > nums.size() - k) return 0; // not enough item case + if(mem[pos][count] != -1) return mem[pos][count]; // Repeating sub-problem + + // Don't start subarray here + int dont_start = findMaxSum(nums, pos + 1, count, k); + + // Start subarray here + int start_here = findMaxSum(nums, pos + k, count + 1, k) + + + prefix_sum[pos + k] - prefix_sum[pos]; + + return mem[pos][count] = max(dont_start, start_here); + } + + void findMaxSumPath(vector &nums, int pos, int count, int &k, vector &path) { + if(count == 3) return; + if(pos > nums.size() - k) return; + + // Don't start subarray here + int dont_start = findMaxSum(nums, pos + 1, count, k); // In O(1) time + + // Start subarray here + int start_here = findMaxSum(nums, pos + k, count + 1, k) // In O(1) time + + prefix_sum[pos + k] - prefix_sum[pos]; + + if(start_here >= dont_start) { + path.push_back(pos); + findMaxSumPath(nums, pos + k, count + 1, k, path); // Include pos + } else { + findMaxSumPath(nums, pos + 1, count, k, path); // Don't include pos + } + } + + vector maxSumOfThreeSubarrays(vector& nums, int k) { + int n = nums.size(); + memset(mem, -1, sizeof(mem)); // + + // Calculate Prefix-Sum + prefix_sum = vector(n + 1, 0); + for(int i=0; i path; + findMaxSumPath(nums, 0, 0, k, path); + + return path; + } +}; + +// Total no. of subproblems = N * 3 = 3N +// Time Complexity - O(N) +// Space Complexity - O(N) + +// Goal: +// 1. Find 3 non-overlapping Subarrays with max sum +// 2. Return list of start indices (lexicographically smallest in case of +// multiple answers) + +// N = 8 +// K = 2 +// No. of K size Subarrays = (N - K + 1) +// SAs = 7 + +// 0, 1, 2, 3, 4, 5, 6, 7 +// Given: [1, 2, 1, 2, 6, 7, 5, 1] +// [0, 1], [3, 4], [5, 6] sum = 23 -- [0, 3, 5] -> this one is lexicographically smaller +// [1, 2], [3, 4], [5, 6] sum = 23 -- [1, 3, 5] + +// result = [0, 3, 5] +// BF -> O(N ** 3) solution, N^2 > 10^8 + +// Recursive Sum, RS(l, r) = Prefix Sum(r) - Prefix Sum(l - 1) + +// Let's find 2 non overlapping Subarrays with maxSum + +// a[] = [2, 3, 1, 5, 2, 7] +// psum[] = [0, 2, 5, 6, 11, 13, 20] + +// 2 * k size = 2 * 2 = 4 + +// Total no. of subproblems = N * 3 = 3N +// Time Complexity - O(N) +// Space Complexity - O(N) + +// Memoization table + +// 1. Count size column +// 2. N size row \ No newline at end of file diff --git a/LeetCode/Algorithms/Hard/MedianOfTwoSortedArrays.cpp b/LeetCode/Algorithms/Hard/MedianOfTwoSortedArrays.cpp new file mode 100644 index 0000000..6af46dc --- /dev/null +++ b/LeetCode/Algorithms/Hard/MedianOfTwoSortedArrays.cpp @@ -0,0 +1,44 @@ +class Solution { + public: + double findMedianSortedArrays(vector& nums1, vector& nums2) { + vector A = nums1, B = nums2; + + int total = nums1.size() + nums2.size(); + int half = total / 2; + + if(B.size() < A.size()) { + swap(A, B); + } + + // log(min(n, m)) + int l = 0, r = A.size() - 1; + while(true) { + int i = (l + r) / 2; // for A + int j = half - i - 2; // B + + // A -> Aright + // B -> Bleft + + // A -> Aleft + // B -> Bright + int Aleft = (i >= 0) ? A[i] : INT_MIN; + int Aright = (i + 1) < A.size() ? A[i + 1] : INT_MAX; + int Bleft = (j >= 0) ? B[j] : INT_MIN; + int Bright = (j + 1) < B.size() ? B[j + 1] : INT_MAX; + + // parition is correct + if(Aleft <= Bright && Bleft <= Aright) { + // if odd + if(total % 2) { + return min(Aright, Bright); + } + // even + return (max(Aleft, Bleft) + min(Bright, Aright)) / 2; + } else if(Aleft > Bright) + r = i - 1; + } else if(Bleft > Bright) { + l = i + 1; + } + } + } +}; \ No newline at end of file diff --git a/LeetCode/Algorithms/Hard/MinimumIntervalToIncludeEachQuery.cpp b/LeetCode/Algorithms/Hard/MinimumIntervalToIncludeEachQuery.cpp new file mode 100644 index 0000000..6105ccf --- /dev/null +++ b/LeetCode/Algorithms/Hard/MinimumIntervalToIncludeEachQuery.cpp @@ -0,0 +1,59 @@ +#define pii pair +class Solution { + public: + struct myComp { + bool operator() (pair &a, pair &b) { + if(a.first == b.first) { + return a.second < b.second; + } + return a.first > b.first; + } + }; + + vector minInterval(vector>& intervals, vector& queries) { + sort(intervals.begin(), intervals.end(), [](vector &a, vector &b) { + return a[0] < b[0]; + }); + + vector sorted_query = queries; + sort(sorted_query.begin(), sorted_query.end()); + + // priority_queue, greater> pq; + priority_queue, myComp> pq; + + int i = 0; + unordered_map m; + for(auto &q: sorted_query) { + // adding all the intervals + while(i < intervals.size() && intervals[i][0] <= q) { + auto &temp = intervals[i]; + int l = temp[0]; + int r = temp[1]; + pq.push({(r - l + 1), r}); + i++; + } + + // removing invalid intervals from + // priority queue + while(!pq.empty() && pq.top().second < q) { + pq.pop(); + } + + if(!pq.empty()) { + m[q] = pq.top().first; + } else { + m[q] = -1; + } + } + + vector result; + for(auto &q: queries) { + result.push_back(m[q]); + } + return result; + } +}; + +// Time Complexity - O(nlogn + qlogq), +// q is length of queries +// n is the lenght of intervals \ No newline at end of file diff --git a/LeetCode/Algorithms/Hard/MinimumWindowSubstring.cpp b/LeetCode/Algorithms/Hard/MinimumWindowSubstring.cpp new file mode 100644 index 0000000..91599cb --- /dev/null +++ b/LeetCode/Algorithms/Hard/MinimumWindowSubstring.cpp @@ -0,0 +1,46 @@ +class Solution { + public: + string minWindow(string s, string t) { + if(t == "") return ""; + + unordered_map countT, window; + + for(auto c: t) { + countT[c]++; + } + + int have = 0, need = countT.size(); + int l = 0; + pair result; + int resLen = INT_MAX; + for(int r=0; rnext; + curr->next = prev; + prev = curr; + curr = futureNode; + } + return prev; + } + ListNode* reverseKGroup(ListNode* head, int k) { + ListNode *temp = head; + ListNode *prevLast = NULL; + + while(temp != NULL) { + ListNode *kthNode = getKthNode(temp, k); + if(kthNode == NULL) { // only when List is larger than K + if(prevLast != NULL) { + prevLast->next = temp; + } + break; + } + + ListNode *nextNode = kthNode->next; + kthNode->next = NULL; + reverseLL(temp); + + if(temp == head) { + head = kthNode; + } else { + prevLast->next = kthNode; + } + + prevLast = temp; + temp = nextNode; + } + return head; + } + + ListNode *getKthNode(ListNode *temp, int k) { + k--; + while(temp != NULL && k > 0) { + temp = temp->next; + k--; + } + return temp; + } +}; + +/* +Time Complexity - O(N) +Space Complexity - O(1) +*/ \ No newline at end of file diff --git a/LeetCode/Algorithms/Hard/TrappingRainWater2.cpp b/LeetCode/Algorithms/Hard/TrappingRainWater2.cpp new file mode 100644 index 0000000..f3e8db0 --- /dev/null +++ b/LeetCode/Algorithms/Hard/TrappingRainWater2.cpp @@ -0,0 +1,62 @@ +class Solution { +public: + #define pi pair> + + bool isValid(int &x, int &y, int &m, int &n) { + return (x >= 0 && x < m && y >= 0 && y < n); + } + int trapRainWater(vector>& heightMap) { + int m = heightMap.size(); + int n = heightMap[0].size(); + + if(m < 3 && n < 3) { + return 0; + } + + // Step-1: Push all boundary elements as START points + priority_queue, greater> minheap; + vector> visited(m, vector(n, false)); + + for(int i=0; i dir = {-1, 0, 1, 0, -1}; // URDL 4-dir calls + while(!minheap.empty()) { + pi curr = minheap.top(); + minheap.pp(); + + int height = curr.first; + int x = curr.second.first; + int y = curr.second.second; + level = max(level, height); + + // 4-directional traversal + for(int i=0; i<4; i++) { + int newX = x + dir[i]; + int newY = x + dir[i + 1]; + if(isValid(newX, newY, m, n) && !visited[newX][newY]) { + visited[newX][newY] = true; + minheap.push(make_pair(heightMap[newX][newY], make_pair(newX, newY))); + if(heightMap[newX][newY] < level) { + trapped_water += level - heightMap[newX][newY]; + } + } + } + } + return trapped_water; + } +}; + +// Time Complexity - O(M * N * log(M * N)), log(M * N) is the heap arrangement, +// M * N is Total Cells +// Space Complexity - O(M * N), visited array min heap + diff --git a/LeetCode/Algorithms/Medium/ConstructStringWithRepeatLimit.cpp b/LeetCode/Algorithms/Medium/ConstructStringWithRepeatLimit.cpp new file mode 100644 index 0000000..fdff5d0 --- /dev/null +++ b/LeetCode/Algorithms/Medium/ConstructStringWithRepeatLimit.cpp @@ -0,0 +1,80 @@ +class Solution { +public: + #define pii pair + string repeatLimitedString(string s, int repeatLimit) { + priority_queue pq; + + vector freq(26, 0); + for(int i=0; i 0) { + pq.push({i, freq[i]}); + } + } + + string result; + while(!pq.empty()) { + pii curr = pq.top(); + pq.pop(); + + char curr_char = 'a' + curr.first; + int count = min(repeatLimit, curr.second); + result.append(count, curr_char); + curr.second -= count; + + if(curr.second > 0) { + if(pq.empty()) { + break; + } + pii next = pq.top(); + pq.pop(); + + char next_char = 'a' + next.first; + + result.push_back(next_char); + next.second--; + if(next.second > 0) { + pq.push(next); + } + pq.push(curr); + } + } + return result; + } +}; + +// Time Complexity - O(N * log(26)) ~ O(n) +// Space Complexity - O(26) ~ O(1), since we're using a max heap of size 26 +// from a to z + +// Goal +// Build lexicographical largest string where no same chars occurs +// more than the repeat limit times + +// s1 = abac +// s2 = abba +// x +// s2 > s1 (b > a) + +// s1 = abb +// s2 = ac +// x +// s2 > s1 (c > b) + +// s1 = abb +// s2 = ab +// s1 > s2 (since size of s1 > s2) + +// build stirng using map +// weightage + +// Greedily place highest valued item to highest weight position +// (2 3 4 7) -> 7 4 3 2 + +// maxheap +// s = aaaabbcccc +// repeat limit = 3 +// ans = cccbcbaaa (a - z (97 - 122)) diff --git a/LeetCode/Algorithms/Medium/ConstructTheLexicographicallyLargestValidSequence.cpp b/LeetCode/Algorithms/Medium/ConstructTheLexicographicallyLargestValidSequence.cpp new file mode 100644 index 0000000..350afec --- /dev/null +++ b/LeetCode/Algorithms/Medium/ConstructTheLexicographicallyLargestValidSequence.cpp @@ -0,0 +1,51 @@ +class Solution { +public: + bool findLargestArray(vector &result, vector &used, int pos, int n) { + if(pos == 2 * n - 1) { + return true; + } + + if(result[pos] != 0) { // already filled + return f(result, used, pos + 1, n); + } + + // Try assigning all unused values + for(int i=n; i>=1; i--) { + if(used[i] == true) continue; + + used[i] = true; + result[pos] = i; + if(i == 1 && findLargestArray(result, used, pos + 1, n)) { + return true; + } + if(i > 1 && (pos + i) < (2 * n - 1) && result[pos + i] == 0) { + result[pos + i] = i; + if(findLargestArray(result, used, pos + 1, n)) { + return true; + } + + result[pos + i] = 0; + } + used[i] = false; + result[pos] = 0; + } + return false; + } + + vector constructDistancedSequence(int n) { + vector used(n + 1, false); + vector result(2 * n - 1, 0); + + findLargestArray(used, result, 0, n); + return result; + } +}; + + +// Time Complexity - O(N!) +// Space Complexity - O(N), depth of recursion + +// Runtime << N! because: +// 1. Equi-distant placement of Nos reduces a lot of arrangements of N! +// 2. Early stopping by greedy recursion + diff --git a/LeetCode/Algorithms/Medium/ContinuousSubarrays.cpp b/LeetCode/Algorithms/Medium/ContinuousSubarrays.cpp new file mode 100644 index 0000000..c4df457 --- /dev/null +++ b/LeetCode/Algorithms/Medium/ContinuousSubarrays.cpp @@ -0,0 +1,77 @@ +class Solution { +public: + #define ll long long + + long long continuousSubarrays(vector& nums) { + int n = nums.size(); + int range_min = INT_MAX; + int range_max = INT_MIN; + int left = 0; + int right; + + ll count = 0; + ll win_size; + + for(right = 0; right < n; right++) { + range_min = min(range_min, nums[right]); + range_max = max(range_max, nums[right]); + + if((range_max - range_min) > 2) { + win_size = right - left; + count += ((win_size) * (win_size + 1)) / 2; + + left = right; + // Expand ranges to current value for right + range_min = nums[right]; + range_max = nums[right]; + + while(abs(nums[right] - nums[left - 1]) <= 2) { + left--; + range_min = min(range_min, nums[left]); + range_max = max(range_max, nums[left]); + } + // Substract overcounted subarrays + if(left < right) { + win_size = (right - left); + count -= (win_size * (win_size + 1)) / 2; + } + } + } + // Add subarrays from last window + win_size = (right - left); + count += ((win_size) * (win_size + 1)) / 2; + return count; + } +}; + +// Time Complexity - O(N) +// Space Complexity - O(1) + +// Constraint: In a Subarray: abs(nums[i] - nums[j]) <= 2 + +// Goal: Count No. of such subarrays + +// Generate all possible Subarrays +// For each Subarray, (max - min) <= 2 +// count++; + +// Counting Subarrays +// No of SAs with size n = (n * (n + 1)) / 2 + +// [5, 3, 4] +// no. of subarrays = (3 * 4) / 2 = 6 + +// [5], [5, 3], [5, 3, 4], [3], [3, 4], [4] + +// range_max = -inf , check |max - min| <= 2 +// rnage_min = inf +// win_size = R - L => total ===> count = (total) * (total + 1) / 2 +// count = 0 + +// L -> x you won't know when to STOP + +// L = R +// then <------ L when the 1st out of bound element comes STOP x + +// Sliding Window (2 Pointer) + diff --git a/LeetCode/Algorithms/Medium/CountTheNumberOfGoodSubarrays.cpp b/LeetCode/Algorithms/Medium/CountTheNumberOfGoodSubarrays.cpp new file mode 100644 index 0000000..b8c13d3 --- /dev/null +++ b/LeetCode/Algorithms/Medium/CountTheNumberOfGoodSubarrays.cpp @@ -0,0 +1,78 @@ +class Solution { + using ll = long long; + public: + long long countGood(vector& nums, int k) { + ll n = nums.size(); + ll left = 0, right = 0; + ll good_subarrays = 0; + unordered_map freq; + ll equal_pairs = 0; + + while(left < n) { + while(right < n and equal_pairs < k) { + freq[nums[right]]++; + if(freq[nums[right]] >= 2) { + equal_pairs += freq[nums[right]] - 1; + } + right++; + } + + if(equal_pairs >= k) { + good_subarrays += n - right + 1; + } + + // remove left item + freq[nums[left]]--; + if(freq[nums[left]] > 0) { + equal_pairs -= freq[nums[left]]; + } + left++; + } + return good_subarrays; + } +}; + +/* +Time Complexity - O(N) +Space Complexity - O(N) + + + 0 1 2 3 4 5 6 7 +[1 5 2 5 3 2 5 6] , K = 2 + +[0, 5] = valid + +n = 8 +n - i = 8 - 5 = 3 + 3 = 6 + +All Subarrays starting from 0 & ending at idx >= 5 will alwys be valid + +count of equal pairs >= k + +maybe starting at idx > 0 and ending at 5 would also be valid! + +Try for increasing left indices unless the Subarray has count of equals pairs < k +=> then extend the right end of subarray + +Two pointer and sliding window + +-> Count Equal pairs + + 0 1 2 3 4 5 6 +[1 2 1 1 2 1 2] + +f(1) = 4 => 3 + 2 + 1 = 3 * 4 / 2 = 6 + +Element | Frequency + 1 4 + 2 3 + +Equal(1, 1) pairs = 4 * 3 / 2 => (n * (n - 1)) / 2 + = 6 + +Equal (2, 2) pairs = 3 * 2 / 2 = 3 + +Total equal pairs = 6 + 3 = 9 + + +*/ \ No newline at end of file diff --git a/LeetCode/Algorithms/Medium/DetectSquares.cpp b/LeetCode/Algorithms/Medium/DetectSquares.cpp new file mode 100644 index 0000000..2c857f1 --- /dev/null +++ b/LeetCode/Algorithms/Medium/DetectSquares.cpp @@ -0,0 +1,37 @@ +class DetectSquares { +public: + unordered_map, int> ptsCount; + vector> points; + DetectSquares() { + + } + + void add(vector point) { + ptsCount[point]++; + points.push_back(point); + } + + int count(vector point) { + int result = 0; + int px = point[0]; + int py = point[1]; + + for(auto &ele: points) { + int x = ele[0]; + int y = ele[1]; + if(abs(py - y) != abs(px - x) or x == px or y == py) { + continue; + } + + result += ptsCount[{x, py}] * ptsCount[{px, y}]; + } + return result; + } +}; + +/** + * Your DetectSquares object will be instantiated and called as such: + * DetectSquares* obj = new DetectSquares(); + * obj->add(point); + * int param_2 = obj->count(point); + */ \ No newline at end of file diff --git a/LeetCode/Algorithms/Medium/DetonateTheMaximumBombs.cpp b/LeetCode/Algorithms/Medium/DetonateTheMaximumBombs.cpp new file mode 100644 index 0000000..7a14afd --- /dev/null +++ b/LeetCode/Algorithms/Medium/DetonateTheMaximumBombs.cpp @@ -0,0 +1,51 @@ +class Solution { + public: + + + int maximumDetonation(vector>& bombs) { + + vector> adj(bombs.size()); + + for(int i=0; i set; + for(int i=0; i &visit) { + if(visit.find(i) != visit.end()) { + return 0; + } + + visit.insert(i); + for(auto nei: adj[i]) { + dfs(nei, visit); + } + return len(visit); + } + }; \ No newline at end of file diff --git a/LeetCode/Algorithms/Medium/FindClosestNodeToGivenTwoNodes.cpp b/LeetCode/Algorithms/Medium/FindClosestNodeToGivenTwoNodes.cpp new file mode 100644 index 0000000..80e9c40 --- /dev/null +++ b/LeetCode/Algorithms/Medium/FindClosestNodeToGivenTwoNodes.cpp @@ -0,0 +1,53 @@ +class Solution { + public: + int closestMeetingNode(vector& edges, int node1, int node2) { + int n = edges.size(); + vector> adj(n); + + // some of the destination nodes can be -1 + // it would also get added in the distance map in bfs traversal + // it won't affect our result because we are traversing + // from 0 to n indexes only + for(int i=0; i node1Dist; // map node -> distance from node1 + unordered_map node2Dist; // map node -> distance fromm node2 + + bfs(node1, node1Dist, adj); + bfs(node2, node2Dist, adj); + + int res = -1; + int resDist = INT_MAX; + + for(int i=0; i distMap, vector> &adj) { + queue> q; + q.push({src, 0}); + distMap[src] = 0; + while(!q.empty()) { + auto temp = q.front(); + int node = temp.first; + int dist = temp.second; + + for(auto &nei: adj[node]) { + if(distMap.find(i) == distMap.end()) { + q.push({nei, dist + 1}); + distMap[nei] = dist + 1; + } + } + } + } + }; \ No newline at end of file diff --git a/LeetCode/Algorithms/Medium/FlipColumnsForMaximumNumberOfEqualRows.cpp b/LeetCode/Algorithms/Medium/FlipColumnsForMaximumNumberOfEqualRows.cpp new file mode 100644 index 0000000..6a1da97 --- /dev/null +++ b/LeetCode/Algorithms/Medium/FlipColumnsForMaximumNumberOfEqualRows.cpp @@ -0,0 +1,30 @@ +class Solution { +public: + int maxEqualRowsAfterFlips(vector>& matrix) { + unordered_map m; + int count = 0; + for(auto &mat: matrix) { + string s = ""; + for(auto &ele: mat) { + s += to_string(ele); + } + + if(s[0] == '1') { + for(int i=0; i>& grid) { + int n = grid[0].size(); + if(n < 2) return 0; + + ll minSum = LONG_MAX; // remember this is LONG_MAX + ll bottomSum = 0; + ll topSum = accumulate(grid[0].begin(), grid[0].end(), 0LL); + + for(int i=0; i + + +Robo-2 picks = max(top sum, bottom sum) + +Robo-1 will choose a partition point which +minimizes the value for Robo-2 pick + +for(pp=0; pp& nums) { + int left =0 ; + int right = 0; + int max_window_size = 0; + int curr_sum = 0; + int curr_xor = 0; + int n = nums.size(); + + while(left <= right && right < n) { + curr_sum += nums[right]; + curr_xor ^= nums[right]; + + while(curr_xor != curr_sum) { + curr_sum -= nums[left]; + curr_xor ^= nums[left]; + left++; + } + + max_window_size = max(max_window_size, right - left + 1); + right++; + } + return max_window_size; + } +}; + +/* + +Time Complexity - O(N) +Space Complexity - O(1) + +Bitwise AND + + x ---> 8 ----> 1000 + & y ---> 6 ----> 0110 + ? 0 0000 + +If not set bits occur at same position then Bitwise AND is always 0 + + x -> 10 ---> 1010 + y -> 6 ---> & 0110 + 0010 (non-zero) + +Bitwise and with sum + +If x and y have no set bits at the same position then + +x ^ y = x + y , this means Bitwise and will be 0 + + | +(10) x ---> 1010 (10) x ---> 1010 +(4) y ---> ^ 0100 (6) y ---> ^ 0110 +(14) x^y ---> 1110 (12) x^y ---> 1100 (not equal) +Equal + +10 + 6 = 16 + +Note: If x and y have corresponding set bits at the same position then XOR +will make it 0 in result + +// XOR decreases value in this case + +Nice Subarray + + Goal: find longest subarray starting at index 0 + 0 1 2 3 +[8, 5, 2, 6] + + + 8 4 2 1 +8 - 1 0 0 0 +5 - 0 1 0 1 +2 - 0 0 1 0 +6 - 0 1 1 0 + +curr_sum = 0 -> 8 -> 13 -> 15 -> 21 - 8 = 13 - 5 = 8 - 2 = 6 +xor_sum = 0 -> 8 -> 13 -> 15 -> 9 -> 1 (xor 5) -> 4 (xor 2) -> 6 (both equal) + +when it seases to be valid, remove 8 from 21 (take xor with 8 and minus 8 from sum) + +8 ^ 8 = 0 + +1 1 0 1 +0 0 1 0 ^ +1 1 1 1 +0 1 1 0 ^ +1 0 0 1 + +1 0 0 1 - 9 +1 0 0 0 - 8 (xor) +0 0 0 1 - 1 +0 1 0 1 - 5 (xor) +0 1 0 0 - 4 +0 0 1 0 -> 2 (xor) +0 1 1 0 -> 6 + +max_window_size +curr_sum = 0 +xor_sum = 0 + +while(left <= right && right < n) { + curr_sum += a[right]; + curr_xor ^= a[right]; + + if(curr_sum == curr_xor) { + right++; + } else { + curr_sum -= a[left]; + curr_xor ^= a[left]; + left++; + } + + max_window_size = max(max_window_size, right -left + 1); +} +*/ + diff --git a/LeetCode/Algorithms/Medium/MakeLexicographicallySmallestArrayBySwappingElements.cpp b/LeetCode/Algorithms/Medium/MakeLexicographicallySmallestArrayBySwappingElements.cpp new file mode 100644 index 0000000..f7391dd --- /dev/null +++ b/LeetCode/Algorithms/Medium/MakeLexicographicallySmallestArrayBySwappingElements.cpp @@ -0,0 +1,127 @@ +class Solution { +public: + vector lexicographicallySmallestArray(vector& nums, int limit) { + + int n = nums.size(); + + // Step - 1: find location of each number + vector> copy; + for(int i=0; i pos = {copy[left].second}; + while(right < n && abs(copy[right-1].first - copy[right].first) <= limit) { + pos.push_back(copy[right].second); + right++; + } + + // order indices + sort(pos.begin(), pos.end()); + + // Place ordered values to ordered indices in original array + for(int i=0; i O(N^2) + LIMIT Swap Constraint + +TC = O(N^2) +Nmax = 10^5 + +// N^2 = 10^10 (TLE) + +Observation - 1 + +a[] = [10 3 5 11 2 8], limit = 2 +swapable groups: (8, 10, 11), (2, 3, 5) + +1. Elements form swappable groups +2. Swapping is only possible within indices of group elements + +Goal: +1. Find the groups with respective indices +2. Order the items group-wise (Sort within each group) + +Note: Simple sorting won't work because of LIMIT swap criteria + +Observation - 2 +All group elements will always occur together after sorting + 0 1 2 3 4 5 +a[] = [10 3 5 11 2 8], limit = 2 + +a[] = [2 3 5 8 10 11] - sorted + --G1- --G2--- + +Observation - 3 +It will always be possible to rearrange a group in such a way that it will be sorted + + 0 1 2 3 4 5 +a[] = [10 20 8 18 7 5] + +0 2 4 5 +10 8 7 5 (group 1) +5 7 8 10 (sorted) + +How to Solve: + +Step1: Get Ordered Groups with Indices +a[] = [10 3 5 11 2 8] + +copy[] = [(10, 0), (3, 1), (5, 2), (11, 3), (2, 4), (8, 5)] + + 0 1 2 3 4 5 +copy_sorted[] = [(2, 4), (3, 1), (5, 2) (8, 5), (10, 0), (11, 3)] + +-> Sorting brings same group items together +-> Indices help identify their actual location in input array + +Step2: Order the Items (Two Pointer + Sorting Indices + Placing Values) + +a[] = [10, 3, 5, 11, 2, 8] + +Copy Sorted[]: [(2, 4), (3, 1), (5, 2), (8, 5), (10, 0), (11, 3)] -> O(NlogN) + +4, 1, 2 +1, 2, 4 -> sorted -> O(NlogN) + +5, 0, 3 +0, 3, 5 -> sorted + +Time Complexity - O(NlogN) +Space Complexity - O(N), since using copy array +*/ \ No newline at end of file diff --git a/LeetCode/Algorithms/Medium/MaximumBeautyOfAnArrayAfterApplyingOperation.cpp b/LeetCode/Algorithms/Medium/MaximumBeautyOfAnArrayAfterApplyingOperation.cpp new file mode 100644 index 0000000..f5778bd --- /dev/null +++ b/LeetCode/Algorithms/Medium/MaximumBeautyOfAnArrayAfterApplyingOperation.cpp @@ -0,0 +1,32 @@ +class Solution { +public: + int maximumBeauty(vector& nums, int k) { + sort(nums.begin(), nums.end()); + + int n = nums.size(); + int win_count = 0; + int max_count = 0; + + int left = 0, right = 0; + while(right < n) { + // find valid window of max size + while(right < n && (nums[right] - nums[left] <= 2 * k)) { + win_count++; + right++; + } + + max_count = max(max_count, win_count); + if(right == n) break; + + // skip left to again make window vlaid + while(left <= right && (nums[right] - nums[left] > 2 * k)) { + win_count--; + left++; + } + } + return max_count; + } +}; + +// Time Complexity - O(NlogN) +// Space Complexity - O(1) \ No newline at end of file diff --git a/LeetCode/Algorithms/Medium/MaximumXorForEachQuery.cpp b/LeetCode/Algorithms/Medium/MaximumXorForEachQuery.cpp new file mode 100644 index 0000000..2b825ee --- /dev/null +++ b/LeetCode/Algorithms/Medium/MaximumXorForEachQuery.cpp @@ -0,0 +1,23 @@ +class Solution { +public: + vector getMaximumXor(vector& nums, int maximumBit) { + int n = nums.size(); + vector result(n, 0); + int xor = 0; + + for(auto &n: nums) { + xor ^= n; + } + + int mask = pow(2, maximumBit) - 1 + + for(int i=n-1; i>=0; i--) { + result.push_back(xor ^ mask); + + // remove the last element each time + xor ^= nums[i]; + } + + return result; + } +}; \ No newline at end of file diff --git a/LeetCode/Algorithms/Medium/MeetingRooms2.cpp b/LeetCode/Algorithms/Medium/MeetingRooms2.cpp new file mode 100644 index 0000000..f8e967f --- /dev/null +++ b/LeetCode/Algorithms/Medium/MeetingRooms2.cpp @@ -0,0 +1,43 @@ +/** + * Definition of Interval: + * class Interval { + * public: + * int start, end; + * Interval(int start, int end) { + * this->start = start; + * this->end = end; + * } + * } + */ + + class Solution { + public: + int minMeetingRooms(vector& intervals) { + vector start, end; + for(int i=0; i& nums, int p) { + int n = nums.size(); + sort(nums.begin(), nums.end()); + + + int l = 0, r = 10e9; + + int res = 10e9; + + while(l <= r) { + int mid = l + (r - l) / 2; + + if(isValid(mid, p)) { + res = mid; + r = mid - 1; + } else { + l = mid + 1; + } + } + return res; + } +}; \ No newline at end of file diff --git a/LeetCode/Algorithms/Medium/MinimizeXOR.cpp b/LeetCode/Algorithms/Medium/MinimizeXOR.cpp new file mode 100644 index 0000000..b7e6ff0 --- /dev/null +++ b/LeetCode/Algorithms/Medium/MinimizeXOR.cpp @@ -0,0 +1,114 @@ +class Solution { +public: + int minimizeXor(int num1, int num2) { + int count = __builtin_popcount(num2); + + int res = 0; + // Cancel set bits from highest to lowest weight + for(int i=31; i>=0 and count; i--) { + if(num1 & (1 << i)) { // If in num1 the highest bit is set + count--; // decrement the count + res += (1 << i); // increment res with whatever is the bit set + } + } + + // set bits lowesst to highest weight + for(int i=0; i<32 and count; i++) { + if((num1 & (1 << i)) == 0) { // In num1 when bit is not set, then try to set the bit for res + count--; + res += (1 << i); // add the set bit in res + } + } + return res; + } +}; + +/* + +Time Complexity - O(logN) ~ O(1), : int -> 32 bits +Space Complexity - O(1) + +a = 8 0 1 0 0 0 +b = 21 1 0 1 0 1 + +set_bits_b = 3 +set_bits in result = 3 (wanted) + +Find X such that x ^ a = Minimal + +res = min (1 ^ 8, 2 ^ 8, 3 ^ 8 ...) + +result = 11 + +x = 1 +x = 2 +. +. +. +x = 10^9 (TLE), iterate through all numbers gives TLE + + +Find No. of Set bits + +set_bits = 0; +while(N) { + N = N & (N - 1); // you'll loose the significant digit each time + set_bits++; +} + + N = 10100 +& N-1 = 10011 + N = 10000 +& N-1 = 01111 + N = 00000 + +set_bits = __buildin_popcount(N); +TC = O(logN) + + +Build Minimal X + +a = 8 -> 0 1 0 0 0 +b =21 -> 1 0 1 0 1 + +set_bits_b = 3 + 16 8 4 2 1 +let x = 0 0 0 0 0 = 11 +^ a = 0 1 0 0 0 + 0 0 0 1 1 = 3 + +Steps: +To minimize XOR b/w x & a +1. Place set bits corresponding to a's set_bits +2. Leftover set bits must be placed to least weighted idx + +a = 21 10101 +b = 2 00010 + +set_bits_b = 1 + + 4 3 2 1 0 + a = 1 0 1 0 1 +^ x = 0 0 0 0 0 => 16 + 0 0 1 0 1 + +a = 20 1 0 1 0 1 +b = 30 1 1 1 1 0 + +set_bits = 4 + +a = 1 0 1 0 1 +1 (minimum weight indices) +x = 0 0 0 0 0 -> 1 0 1 0 1 -> 1 0 1 1 1 => 23 + +a = 1 0 1 0 1 +x = 1 0 1 1 1 + 0 0 0 1 0 + +Time Complexity - O(logN) ~ O(1), : int -> 32 bits +Space Complexity - O(1) + + + +Cancel set bits from highest to lowest weight +Put set bits from lowest to highest weight +*/ \ No newline at end of file diff --git a/LeetCode/Algorithms/Medium/MinimizedMaximumOfProductsDistributedToAnyStore.cpp b/LeetCode/Algorithms/Medium/MinimizedMaximumOfProductsDistributedToAnyStore.cpp new file mode 100644 index 0000000..cdcd488 --- /dev/null +++ b/LeetCode/Algorithms/Medium/MinimizedMaximumOfProductsDistributedToAnyStore.cpp @@ -0,0 +1,44 @@ +class Solution { +public: + int minimizedMaximum(int n, vector& quantities) { + // quantities[i] -> number of products of ith product type + + // 1. store can given at most one product type, can be given any amount of it + // 2. + + int n = quantities.size(); + int low = 1; + int high = *max_element(quantities.begin(), quantities.end()); + int ans = INT_MAX; + + while(low <= high) { + mid = low + (high - low) / 2; + + if(canAssign(mid, n, quantities)) { + ans = min(ans, mid); + high = mid - 1; + } else { + low = mid + 1; + } + } + return ans; + } + + bool canAssign(int mid, int n, vector &quantities) { + int count = 0; + for(int i=0; i getBin(int n) { + vector res; + + while(n) { + if(n & 1 == 1) res.push_back(1); + else res.push_back(0); + n>>=1; + } + return res; + } + long long minEnd(int n, int x) { + // size - n + // bitwise and operation b/w all elements i x + + if(n == 1) return x; + + // Step 1: Record zero positions + vector zero_pos; + int count = 0; + int val = x; + while(val) { + if((val & 1) == 0) { + zero_pos.push_back(count); + } + count++; + val>>=1; + } + + // Step 2: Find no. of bits required to make N combinations + int req_bits = ceil(log2(n)); + + // Step 3: Append more bits in zero_pos as per requirement + for(int i=zero_pos.size(); i append_bits = getBin(n-1); + + // Step 5: Form the answer + ll ans = x; + int pos = append_bits.size(); + while(pos--) { + if(append_bits.back() == 1) { + ans += pow(2, zero_pos[pos]) * append_bits[pos]; + } + } + + return ans; + + } +}; + +// Dry run + +// N = 4, X = 5 - time complexity - O(logN), space complexity - O(logN) +// 1. zero_pos[] = [1] => O(logN) +// 2. read_bits = [log2 4] = 2 +// 3. Push extra zeros if needed zero_pos[]: [1, 3] +// 4. Get binary of (n - 1) = 3 (11) +// 5. Update bits at zero_pos and return \ No newline at end of file diff --git a/LeetCode/Algorithms/Medium/MinimumNumberOfOperationsToSortABinaryTreeByLevel.cpp b/LeetCode/Algorithms/Medium/MinimumNumberOfOperationsToSortABinaryTreeByLevel.cpp new file mode 100644 index 0000000..ea687d1 --- /dev/null +++ b/LeetCode/Algorithms/Medium/MinimumNumberOfOperationsToSortABinaryTreeByLevel.cpp @@ -0,0 +1,108 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +public: + int findMinSwaps(vector &values) { + int min_swaps = 0; + + // store K->values ... V->Actual_idx ordered map + map sorted_map; + for(int i=0; i visited(values.size(), false); // this marks already processed indices + + for(auto &[val, idx]: sorted_map) { + if(visited[idx]) { // don't process if already done + iteration++; + continue; + } + + visited[idx] = true; + int len = 1; // find length of cycle + while(idx != iteration) { + idx = sorted_map[values[idx]]; + visited[idx] = true; + len++; + } + min_swaps += len-1; // add no. of swaps for the current + iteration++; + } + return min_swaps; + } + + int minimumOperations(TreeNode* root) { + queue q; + q.push(root); + + int min_swaps = 0; + while(!q.empty()) { + int size = q.size(); + vector values; + for(int i=0; ival); + + if(node->left) { + q.push(node->left); + } + + if(node->right) { + q.push(node->right); + } + } + min_swaps += findMinSwaps(values); + } + return min_swaps; + } +}; + +// Time Complexity - O(N + NlogN + NlogN) ~ O(NlogN), sorting and map +// traversig n nodes +// NlogN since we're using a sorted map +// NlogN since we're using a sorted array +// Space Complexity - O(N), since we're using a map + +// Example: node values are [7, 11, 3, 5, 2]. +// The index array, after sorting, will look like this: [3, 4, 1, 2, 0]. + +// Optimal, tree, sorting, BFS + +// Note: Unsorted array always exists as cycle +// a[] = [3 1 2] +// 0 1 2 + +// WE need 1- rotation of cycle to sort +// cycle size = 2 = (n - 1), n is the unsorted cycle size +// in 1 step only 1 element gets placed in correct position +// in last step 2 elements get placed in their correct position + +// Cycle size = 3, no. of swaps = 2 + +// Swaps to Sort = Cycle length - 1 + +// skip swap when: +// 1. iteration == idx +// 2. visited == true + +// step 1- build a sorted map +// step 2: sort values to get index of elements in a sorted array +// step 3: iterate over each item in sorte dmap and find cycle length starting +// at given idx + +// \ No newline at end of file diff --git a/LeetCode/Algorithms/Medium/MinimumOperationsToMakeAUniValueGrid.cpp b/LeetCode/Algorithms/Medium/MinimumOperationsToMakeAUniValueGrid.cpp new file mode 100644 index 0000000..2a29c61 --- /dev/null +++ b/LeetCode/Algorithms/Medium/MinimumOperationsToMakeAUniValueGrid.cpp @@ -0,0 +1,100 @@ +class Solution { + public: + int minOperations(vector>& grid, int x) { + // add x or substract x from any eleemnt in grid + + // minimum no. of opertions to make grid uni-value else -1 + + vector array; + int remainder = grid[0][0]%x; + // Step 1: insert the array elements + for(int i=0; i 10^8 + +Pair Equality + +Goal: 1. Make a & b equal +a = 10, b = 30 + +2. Do it in min steps +x = 5 +{For a pair (a, b) any point from a to b will be optimal} + +Note: +1. a and b can become equal only when a % x == b % x + +c = 12 % 5 = 2 e = 10 % 5 = 0 +d = 32 % 5 = 2 f = 31 % 5 = 1 +x = 5 x = 5 + +Array Uni-value + +a[] = [9, 14, 29, 39], x = 5 + +if a[i] % x is same for all elements then they can meet + +if all pairs(c, d) where c % x == d % x then the array +can be made uni-value more optmially + +if a[i] % x is same for all i -> 0 to (N - 1), +then the array can be made uni-value + + +meeting point + + 9 14 (19) (24) 29 39 -- even (find the points within two middle points) + + 9 14 29 34 39 -- odd (take middle element) + + +9 29 +39 14 + +Flatten - [9, 29, 39, 14] -> mn + +[9, 14, 29, 39] --> mnlogmn + +median = N / 2 = 2 + +// meet at index = 2 + +Iterate and check remainder whilte flattening + +rem = 9 % 5 = 4 + +steps += abs(a[i] - a[median]) / x + +steps = 0 -> 4 -> 7 -> 9 +*/ \ No newline at end of file diff --git a/LeetCode/Algorithms/Medium/MultiplyStrings.cpp b/LeetCode/Algorithms/Medium/MultiplyStrings.cpp new file mode 100644 index 0000000..7a944eb --- /dev/null +++ b/LeetCode/Algorithms/Medium/MultiplyStrings.cpp @@ -0,0 +1,38 @@ +class Solution { +public: + string multiply(string num1, string num2) { + if(num1 == "0" || num2 == "0") { + return "0"; + } + + int m = num1.size(); + int n = num2.size(); + + vector result(m + n, 0); + + reverse(num1.begin(), num1.end()); + reverse(num2.begin(), num2.end()); + + for(int i=0; i& nums) { + + int prev = 0; + + // O(n * m * sqrt(m)) + for(auto &n : nums) { + int upper_bound = n - prev; // non-inclusive [2, n) + int largest_p = 0; + + for(int i=upper_bound-1; i>=2; i--) { + if(is_prime(i)) { + largest_p = i; + break; + } + } + + if((n - largest_p) <= prev) { + return false; + } + + prev = n - largest_p; + + } + } + + bool isPrime(int n) { + for(int i=2; i& arr) { + // remove prefix + int n = arr.size(); + int r = n-1; + + while(r > 0 && arr[r-1] > arr[r]) { + r--; + } + + int res = r; + + // remove postfix + int l = 0; + while(l + 1 < n && arr[l] < arr[l + 1]) { + l++; + } + + res = min(res, n - l - 1); + + // remove middle + l = 0 + r = n-1; + while(l < r) { + // shrink the valid window (make it l+1 so that res is not negative when both r and l are equal) + while(r < n && (l + 1) < r && arr[r-1] <= arr[r] && arr[l] <= arr[r]) { + r--; + } + + // [1, 2, 3, 10, 6, 1, 2, 3] + + // Expand Invalid Window + while(r < n && arr[l] > arr[r]) { + r++; + } + + res = min(res, r - l - 1); + + if(arr[l] > arr[l + 1]) { + break; + } + l += 1; + } + return res; + } +}; + +// 1. Prefix +// 2. Postfix +// 3. Middle +// Take the minimum of all 3 above + +// Time Complexity - O(N) +// Space Complexity - O(1) + +// Method - 2 + +class Solution { +public: + int findLengthOfShortestSubarray(vector& arr) { + int n = arr.size(); + int l = 0; + int r = n-1; + // remove prefix + while(r >0 && arr[r-1] <= arr[r]) { + r--; + } + + int res = r; + + // l r + // remove middle and postfix -- [1, 10, 6, 1, 2, 3] + l = 0; + while(l < r) { + + // Expand Invalid Window + while(r < n && arr[l] > arr[r]) { + r++; + } + + res = min(res, r - l - 1); + + if(arr[l + 1] < arr[l]) { + break; + } + l++; + } + return res; + } +}; + +// 1. Prefix +// 2. Postfix +// 3. Middle +// Take the minimum of all 3 above + +// Time Complexity - O(N) +// Space Complexity - O(1) \ No newline at end of file diff --git a/LeetCode/Algorithms/Medium/ShortestSubarrayWithOrAtLeastK2.cpp b/LeetCode/Algorithms/Medium/ShortestSubarrayWithOrAtLeastK2.cpp new file mode 100644 index 0000000..f02701a --- /dev/null +++ b/LeetCode/Algorithms/Medium/ShortestSubarrayWithOrAtLeastK2.cpp @@ -0,0 +1,65 @@ +class Solution { +public: + void updateFreq(vector &bitFreq, int val) { + for(int i=0; i<32; i++) { + if(number & (1< &bitFreq) { + int number = 0; + long long pow = 1; + for(int i =0; i<32; i++) { + if(bitFreq[i] > 0) { + number += pow; + } + pow *= 2; + } + return number; + } + + int minimumSubarrayLength(vector& nums, int k) { + // A ^ B = + + // 0 ^ 0 = 1 + + // Find bit value of k + + // find all + + if(k == 0) { + return 1; + } + + int n = nums.size(); + int shortest = INT_MAX; + int left = 0, right = 0; + int currOR = 0; + vector bitFreq(32);o + + while(right < n) { + updateFreq(bitFreq, nums[right], 1); + currOR |= nums[right]; + + // resize window + while(left <= right and currOR >= k) { + shortest = min(shortest, right - left + 1); + updateFreq(bitFreq, nums[left], -1); + currOR = getNumber(bitFreq); + left++; + } + right++; + } + return shortest == INT_MAX ? -1: shortest; + } +}; + +// Observations + +// 1. 0 or 0 or ... or 0 or 1 = 1 +// 2. OR for +ve nos will always be non-decreasing + +// In non-decreasing curve to find smallest subarray use sliding window + diff --git a/LeetCode/Algorithms/Medium/TakeKOfEachCharacterFromLeftAndRight.cpp b/LeetCode/Algorithms/Medium/TakeKOfEachCharacterFromLeftAndRight.cpp new file mode 100644 index 0000000..360f2d9 --- /dev/null +++ b/LeetCode/Algorithms/Medium/TakeKOfEachCharacterFromLeftAndRight.cpp @@ -0,0 +1,42 @@ +class Solution { +public: + int takeCharacters(string s, int k) { + // minimum no . of minutes to take atleast k of each character + + // total counts + int a=0, b=0, c =0; + int n = s.size(); + for(auto &ch: s) { + if(ch == 'a') a++; + if(ch == 'b') b++; + if(ch == 'c') c++; + } + + if(min(a, min(b, c)) < k) { + return -1; + } + + // Sliding Window + int l=0; + int result = 0; + int ans = INT_MAX; + for(int r=0; r>& events) { + // starttime, endtime, value + // maximize sum + + vector> line_sweep; + + for(auto &event: events) { + int startTime = event[0]; + int endTime = event[1]; + int value = event[2]; + + line_sweep.push_back({startTime, 1, value}); + line_sweep.push_back({endTime + 1, -1, value}); + } + + sort(line_sweep.begin(), line_sweep.end()); + + int max_val = 0; + int max_seen = 0; + + for(auto &event: line_sweep) { + int point = event[0]; + int status = event[1]; + int value = event[2]; + + if(status == 1) { + max_val = max(max_val, max_seen + value); + } else if(status == -1) { // End + max_seen = max(max_seen, value); + } + } + return max_val; + } +}; + +// Time Complexity - O(NlogN), sorting the array +// Space Complexity - O(N), since we're building a vector of size n + +// 1. Solve Left to right +// 2. If current event is included +// then currSum = maxSeen on left + curr Value +// 3. Maximize currSum + +// Convert Inclusive range 6o exclusive + +// |----------| +// 1 3 +// |------------------0 +// 1 4 + +//1 |----------| 3 +// 3|------------| 6 +// |---------------0 +// 1 4 +// 3|------------| 6 + +// Line-Sweep 1D : For Interval Problems + +// Events - [1, 3, 2], [3, 6, 4], [5, 8, 3], [10, 12, 3] + +// 2 +// 1 |----------| 3 (4) +// 3 |----------| 6 +// 3 +// 5 |----------| 8 + + +// 2 +// 1 |--------------0 4 +// 3 |---------------0 7 +// 3 +// 5 |--------------0 9 + +// status - 1 (include) +// status - 0 (not included) + + +// max_seen updated when interval ends