diff --git a/Domains/CompetitiveProgramming/Programs/C++/Binary Tree Maximum Path Sum.cpp b/Domains/CompetitiveProgramming/Programs/C++/Binary Tree Maximum Path Sum.cpp new file mode 100644 index 00000000..902558df --- /dev/null +++ b/Domains/CompetitiveProgramming/Programs/C++/Binary Tree Maximum Path Sum.cpp @@ -0,0 +1,82 @@ +/* +Problem: Binary Tree Maximum Path Sum +Platform: LeetCode +Problem Code: 124 +Difficulty: Hard +Link: https://leetcode.com/problems/binary-tree-maximum-path-sum/ + +A path in a binary tree is a sequence of nodes where each pair of adjacent nodes +has an edge connecting them. A node can appear in the path at most once. The path +does not necessarily need to pass through the root. + +The path sum of a path is the sum of the node's values in the path. + +Given the root of a binary tree, return the maximum path sum of any non-empty path. + +Example 1: +Input: root = [1,2,3] +Output: 6 +Explanation: The optimal path is 2 → 1 → 3, which gives a path sum of 6. + +Example 2: +Input: root = [-10,9,20,null,null,15,7] +Output: 42 +Explanation: The optimal path is 15 → 20 → 7, which gives a path sum of 42. + +Approach: +1. Use post-order DFS traversal to compute the maximum path sum passing through each node. +2. For every node, calculate: + - `l_sum`: maximum sum path in the left subtree. + - `r_sum`: maximum sum path in the right subtree. +3. The best path through the current node could include: + - only the node value, + - the node and left subtree, + - the node and right subtree, + - or both subtrees through the node. +4. Update a global `max_sum` with the maximum path found so far. +5. Return to the parent the maximum single-path sum (either left or right) plus current node value. + +Time Complexity: O(n) — each node is visited once. +Space Complexity: O(h) — recursion stack, where h is the height of the tree. + +Contributor: shwetakul2005 +*/ + +#include +using namespace std; + +// 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 calc_sum(TreeNode* root, int& max_sum) { + if (root == NULL) return 0; + + int l_sum = calc_sum(root->left, max_sum); + int r_sum = calc_sum(root->right, max_sum); + + int c_sum = root->val; + if (l_sum > 0) c_sum += l_sum; + if (r_sum > 0) c_sum += r_sum; + + // Update global maximum + max_sum = max(max_sum, c_sum); + + // Return maximum path sum for parent usage + return max(0, max(l_sum, r_sum)) + root->val; + } + + int maxPathSum(TreeNode* root) { + int max_sum = root->val; + calc_sum(root, max_sum); + return max_sum; + } +}; diff --git a/Domains/CompetitiveProgramming/Programs/C++/Insert into a Binary Search Tree.cpp b/Domains/CompetitiveProgramming/Programs/C++/Insert into a Binary Search Tree.cpp new file mode 100644 index 00000000..db3a5100 --- /dev/null +++ b/Domains/CompetitiveProgramming/Programs/C++/Insert into a Binary Search Tree.cpp @@ -0,0 +1,57 @@ +/* +Problem: Insert into a Binary Search Tree +Platform: LeetCode +Problem Code: 701 +Difficulty: Medium +Link: https://leetcode.com/problems/insert-into-a-binary-search-tree/ + +Given the root of a binary search tree (BST) and a value to insert into the tree, +insert the value into the BST. Return the root of the BST after the insertion. +It is guaranteed that the new value does not exist in the original BST. + +Notice that there may exist multiple valid ways for the insertion, as long as the tree +remains a BST after insertion. You can return any of them. + +Example 1: +Input: root = [4,2,7,1,3], val = 5 +Output: [4,2,7,1,3,5] + +Example 2: +Input: root = [40,20,60,10,30,50,70], val = 25 +Output: [40,20,60,10,30,50,70,null,null,25] + +Approach: +1. Recursively traverse the tree to find the correct position for the new value. +2. If the value is less than the current node, go to the left subtree. +3. If the value is greater, go to the right subtree. +4. When a NULL position is found, create a new node with the given value. +5. Return the root of the updated BST. + +Time Complexity: O(h), where h is the height of the BST. +Space Complexity: O(h) due to recursion stack. + +Contributor: shwetakul2005 +*/ + +#include +using namespace std; + +// 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: + TreeNode* insertIntoBST(TreeNode* root, int val) { + if (root == NULL) return new TreeNode(val); + if (val < root->val) root->left = insertIntoBST(root->left, val); + else root->right = insertIntoBST(root->right, val); + return root; + } +}; diff --git a/Domains/CompetitiveProgramming/Programs/C++/Merge k Sorted Lists.cpp b/Domains/CompetitiveProgramming/Programs/C++/Merge k Sorted Lists.cpp new file mode 100644 index 00000000..317bdcb3 --- /dev/null +++ b/Domains/CompetitiveProgramming/Programs/C++/Merge k Sorted Lists.cpp @@ -0,0 +1,77 @@ +/* +Problem: Merge k Sorted Lists +Platform: LeetCode +Problem Code: 23 +Difficulty: Hard +Link: https://leetcode.com/problems/merge-k-sorted-lists/ + +You are given an array of k linked-lists, each linked-list is sorted in ascending order. +Merge all the linked-lists into one sorted linked-list and return it. + +Example 1: +Input: lists = [[1,4,5],[1,3,4],[2,6]] +Output: [1,1,2,3,4,4,5,6] + +Example 2: +Input: lists = [] +Output: [] + +Example 3: +Input: lists = [[]] +Output: [] + +Approach: +1. Traverse through each linked list and push all node values into a min-heap (priority queue). +2. Extract the smallest element one by one from the heap to form a new sorted linked list. +3. This approach ensures a sorted result, though it uses extra memory for all node values. + +Time Complexity: O(N log N) where N is the total number of nodes (since we push and pop each node in the heap). +Space Complexity: O(N) for storing all values in the priority queue. + +Contributor: shwetakul2005 +*/ + +#include +using namespace std; + +// Definition for singly-linked list. +struct ListNode { + int val; + ListNode *next; + ListNode() : val(0), next(nullptr) {} + ListNode(int x) : val(x), next(nullptr) {} + ListNode(int x, ListNode *next) : val(x), next(next) {} +}; + +class Solution { +public: + ListNode* mergeKLists(vector& lists) { + int n = lists.size(); + priority_queue, greater> pq; // min-heap + + // Step 1: Push all node values into heap + for (int i = 0; i < n; i++) { + ListNode* temp = lists[i]; + while (temp != nullptr) { + pq.push(temp->val); + temp = temp->next; + } + } + + // Step 2: Handle empty case + if (pq.empty()) return nullptr; + + // Step 3: Construct the new sorted list + ListNode* res = new ListNode(pq.top()); + pq.pop(); + ListNode* temp = res; + + while (!pq.empty()) { + temp->next = new ListNode(pq.top()); + temp = temp->next; + pq.pop(); + } + + return res; + } +}; diff --git a/Domains/CompetitiveProgramming/Programs/C++/Split Array Largest Sum.cpp b/Domains/CompetitiveProgramming/Programs/C++/Split Array Largest Sum.cpp new file mode 100644 index 00000000..72b2a859 --- /dev/null +++ b/Domains/CompetitiveProgramming/Programs/C++/Split Array Largest Sum.cpp @@ -0,0 +1,91 @@ +/* +Problem: Split Array Largest Sum +Platform: LeetCode +Problem Code: 410 +Difficulty: Medium +Link: https://leetcode.com/problems/split-array-largest-sum/ + +Given an array `arr` of non-negative integers and an integer `m`, split the array into `m` non-empty continuous subarrays. +Write an algorithm to minimize the largest sum among these `m` subarrays. + +Example 1: +Input: arr = [7,2,5,10,8], m = 2 +Output: 18 +Explanation: There are four ways to split arr into two subarrays. The best way is [7,2,5] and [10,8], +which has the largest sum = max(7+2+5,10+8) = 18. + +Example 2: +Input: arr = [1,2,3,4,5], m = 2 +Output: 9 + +Approach: +1. Use binary search on the range of possible sums: + - `low = max element of array` (minimum possible largest sum) + - `high = sum of array` (maximum possible largest sum) +2. For a candidate sum `mid`, check if it is possible to split the array into ≤ m subarrays such that no subarray sum exceeds `mid`. +3. If possible, try a smaller `mid` (move `high`), else increase `mid` (move `low`). +4. Continue until `low > high`, and the minimum feasible `mid` is the answer. + +Time Complexity: O(n log(sum-max)), where sum-max = total sum of array minus max element. +Space Complexity: O(1) extra space. + +Contributor: shwetakul2005 +*/ + +#include +using namespace std; + +class Solution { +public: + // Check if we can split array into ≤ m subarrays with max sum ≤ mid + bool ispos(vector& v, int mid, int m) { + int n = v.size(); + int s = 0, cnt = 0; + + for (int i = 0; i < n; i++) { + s += v[i]; + if (s == mid) { + cnt++; + s = 0; + } + else if (s > mid) { + cnt++; + s = v[i]; + if (i == n - 1) { + cnt++; + } + } + else if (s < mid && i == n - 1) { + cnt++; + } + } + + return cnt <= m; + } + + int splitArray(vector& arr, int m) { + int n = arr.size(); + if (n < m) return -1; + + int tot_sum = 0, maxi = INT_MIN; + for (int i = 0; i < n; i++) { + tot_sum += arr[i]; + maxi = max(maxi, arr[i]); + } + + int low = maxi, high = tot_sum; + int ans = tot_sum; + + while (low <= high) { + int mid = low + (high - low) / 2; + if (ispos(arr, mid, m)) { + ans = mid; + high = mid - 1; + } else { + low = mid + 1; + } + } + + return ans; + } +}; \ No newline at end of file diff --git a/Domains/CompetitiveProgramming/Programs/C++/Trapping Rain Water.cpp b/Domains/CompetitiveProgramming/Programs/C++/Trapping Rain Water.cpp new file mode 100644 index 00000000..451cfad7 --- /dev/null +++ b/Domains/CompetitiveProgramming/Programs/C++/Trapping Rain Water.cpp @@ -0,0 +1,69 @@ +/* +Problem: Trapping Rain Water +Platform: LeetCode +Problem Code: 42 +Difficulty: Hard +Link: https://leetcode.com/problems/trapping-rain-water/ + +Given n non-negative integers representing an elevation map where the width of each bar is 1, +compute how much water it can trap after raining. + +Example 1: +Input: height = [0,1,0,2,1,0,1,3,2,1,2,1] +Output: 6 +Explanation: The above elevation map (black section) is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. +In this case, 6 units of rain water (blue section) are being trapped. + +Example 2: +Input: height = [4,2,0,3,2,5] +Output: 9 + +Approach: +1. Use two pointers — one from the left and one from the right. +2. Maintain two variables `leftMax` and `rightMax` to store the maximum height encountered so far from each side. +3. Move the pointer with the smaller height inward. + - If the current height is less than the corresponding max, water can be trapped = max - height. + - Otherwise, update the max height. +4. Continue until both pointers meet. +5. This approach eliminates the need for extra arrays and efficiently computes the trapped water. + +Time Complexity: O(n) +Space Complexity: O(1) + +Contributor: shwetakul2005 +*/ + +#include +using namespace std; + +class Solution { +public: + int trap(vector& height) { + int n = height.size(); + if (n == 0) return 0; + + int left = 0, right = n - 1; + int leftMax = 0, rightMax = 0; + int water = 0; + + while (left < right) { + if (height[left] < height[right]) { + // Update left max + if (height[left] >= leftMax) + leftMax = height[left]; + else + water += leftMax - height[left]; + left++; + } + else { + // Update right max + if (height[right] >= rightMax) + rightMax = height[right]; + else + water += rightMax - height[right]; + right--; + } + } + return water; + } +}; diff --git a/Domains/CompetitiveProgramming/Programs/C++/Vertical Order Traversal of a Binary Tree.cpp b/Domains/CompetitiveProgramming/Programs/C++/Vertical Order Traversal of a Binary Tree.cpp new file mode 100644 index 00000000..f1b12b7d --- /dev/null +++ b/Domains/CompetitiveProgramming/Programs/C++/Vertical Order Traversal of a Binary Tree.cpp @@ -0,0 +1,91 @@ +/* +Problem: Vertical Order Traversal of a Binary Tree +Platform: LeetCode +Problem Code: 987 +Difficulty: Medium +Link: https://leetcode.com/problems/vertical-order-traversal-of-a-binary-tree/ + +Given the root of a binary tree, calculate the vertical order traversal of the binary tree. + +For each node at position (row, col): +- The root is at (0, 0). +- Left child is at (row+1, col-1) +- Right child is at (row+1, col+1) + +Return a list of non-empty reports of nodes for each column sorted from left to right. +- Nodes in the same row and column are sorted by value. + +Example 1: +Input: root = [3,9,20,null,null,15,7] +Output: [[9],[3,15],[20],[7]] + +Example 2: +Input: root = [1,2,3,4,5,6,7] +Output: [[4],[2],[1,5,6],[3],[7]] + +Approach: +1. Perform a DFS traversal of the tree while recording (col, row, value) for each node. +2. Store all nodes in a vector of tuples: (col, row, value). +3. Sort the vector: + - first by column (left to right) + - then by row (top to bottom) + - then by node value (ascending) if row and column are the same +4. Group the sorted nodes by column to get the final vertical order. + +Time Complexity: O(n log n) — due to sorting all n nodes. +Space Complexity: O(n) — for storing node tuples. + +Contributor: shwetakul2005 +*/ + +#include +using namespace std; + +// 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: + // DFS traversal storing (col, row, value) + void traversal(TreeNode* root, vector>& st, int col=0, int row=0){ + if(root == NULL) return; + + st.push_back({col, row, root->val}); + traversal(root->left, st, col-1, row+1); + traversal(root->right, st, col+1, row+1); + } + + vector> verticalTraversal(TreeNode* root) { + vector> st; // store (col, row, value) + traversal(root, st); + + // Sort by column, then row, then value + sort(st.begin(), st.end(), [](const auto& a, const auto& b) { + if (get<0>(a) != get<0>(b)) return get<0>(a) < get<0>(b); + if (get<1>(a) != get<1>(b)) return get<1>(a) < get<1>(b); + return get<2>(a) < get<2>(b); + }); + + // Group by column + vector> ans; + vector res; + int k = get<0>(st[0]); + for (int i = 0; i < st.size(); i++) { + if (get<0>(st[i]) != k) { + ans.push_back(res); + res.clear(); + k = get<0>(st[i]); + } + res.push_back(get<2>(st[i])); + } + if (!res.empty()) ans.push_back(res); + return ans; + } +};