diff --git a/non-overlapping-intervals/Jeehay28.js b/non-overlapping-intervals/Jeehay28.js new file mode 100644 index 000000000..96292bc40 --- /dev/null +++ b/non-overlapping-intervals/Jeehay28.js @@ -0,0 +1,32 @@ +// 🚀 Greedy Algorithm +// ✅ Time Complexity: O(n log n), where n is the number of intervals +// - Sorting the intervals: O(n log n) +// - Iterating through intervals: O(n) + +// ✅ Space Complexity: O(1), No other data structures are used, + +/** + * @param {number[][]} intervals + * @return {number} + */ +var eraseOverlapIntervals = function (intervals) { + // ✅ Sorting by end time ensures that we keep intervals that finish the earliest, reducing the chances of overlap with the subsequent intervals. + // ❌ Sorting by start time would lead to a greedy choice too early, causing unnecessary removals. + intervals.sort((a, b) => a[1] - b[1]); + + let removalCnt = 0; + + let prevEnd = intervals[0][1]; + + for (let i = 1; i < intervals.length; i++) { + const [start, end] = intervals[i]; + + if (start < prevEnd) { + removalCnt += 1; // Increment removal count for an overlap + } else { + prevEnd = end; + } + } + return removalCnt; +}; + diff --git a/remove-nth-node-from-end-of-list/Jeehay28.js b/remove-nth-node-from-end-of-list/Jeehay28.js new file mode 100644 index 000000000..ccca5db72 --- /dev/null +++ b/remove-nth-node-from-end-of-list/Jeehay28.js @@ -0,0 +1,76 @@ +// 🚀 Optimized Approach: Two-Pointer Method (One-Pass) +// ✅ Time Complexity: O(N), where N is the number of nodes +// ✅ Space Complexity: O(1) + +/** + * Definition for singly-linked list. + * function ListNode(val, next) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + */ +/** + * @param {ListNode} head + * @param {number} n + * @return {ListNode} + */ +var removeNthFromEnd = function (head, n) { + let dummy = new ListNode(0, head); + let fast = dummy; + let slow = dummy; + + for (let i = 0; i <= n; i++) { + fast = fast.next; + } + + while (fast) { + fast = fast.next; + slow = slow.next; + } + + slow.next = slow.next.next; + + return dummy.next; +}; + +// ✅ Time Complexity: O(N), where N is the number of nodes +// ✅ Space Complexity: O(1) + +/** + * Definition for singly-linked list. + * function ListNode(val, next) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + */ +/** + * @param {ListNode} head + * @param {number} n + * @return {ListNode} + */ +// var removeNthFromEnd = function (head, n) { +// let length = 0; + +// let node = head; + +// // Compute the length of the linked list +// while (node) { +// length += 1; +// node = node.next; +// } + +// // Create a dummy node pointing to head (helps handle edge cases) +// let dummy = new ListNode(0, head); +// node = dummy; + +// // Move to the node just before the one to be removed +// for (let i = 0; i < length - n; i++) { +// node = node.next; +// } + +// // Remove the nth node from the end by updating the next pointer +// node.next = node.next.next; + +// // Return the modified linked list (excluding the dummy node) +// return dummy.next; +// }; diff --git a/same-tree/Jeehay28.js b/same-tree/Jeehay28.js new file mode 100644 index 000000000..2ec4872e8 --- /dev/null +++ b/same-tree/Jeehay28.js @@ -0,0 +1,69 @@ +// 🚀 Iterative DFS (Stack) +// ✅ Time Complexity: O(n), where n is the number of nodes in the tree +// ✅ Space Complexity: O(n) (worst case), O(log n) (best case for balanced trees) + +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} p + * @param {TreeNode} q + * @return {boolean} + */ +var isSameTree = function (p, q) { + let stack = [[p, q]]; + while (stack.length > 0) { + const [p, q] = stack.pop(); + + if (p === null && q === null) continue; + + if (p === null || q === null) return false; + + if (p.val !== q.val) return false; + + stack.push([p.left, q.left]); + stack.push([p.right, q.right]); + } + + return true; +}; + + + +// 🚀 recursive approach +// ✅ Time Complexity: O(n), where n is the number of nodes in the tree +// ✅ Space Complexity: O(n) (worst case), O(log n) (best case for balanced trees) + +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} p + * @param {TreeNode} q + * @return {boolean} + */ +// var isSameTree = function (p, q) { +// // Base case: If both trees are empty, they are the same +// if (p === null && q === null) return true; + +// // If one of the trees is empty and the other is not, return false +// if (p === null || q === null) return false; + +// // Compare the values of the current nodes +// if (p.val !== q.val) return false; + +// // Recursively compare the left and right subtrees +// return isSameTree(p.left, q.left) && isSameTree(p.right, q.right); +// }; + + diff --git a/serialize-and-deserialize-binary-tree/Jeehay28.js b/serialize-and-deserialize-binary-tree/Jeehay28.js new file mode 100644 index 000000000..0ec299612 --- /dev/null +++ b/serialize-and-deserialize-binary-tree/Jeehay28.js @@ -0,0 +1,92 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ + +// ✅ Time Complexity: O(N), where N is the number of nodes +// ✅ Space Complexity: O(N) + +/** + * Encodes a tree to a single string. + * + * @param {TreeNode} root + * @return {string} + */ + +var serialize = function (root) { + // Serialization (Tree → String) + // Uses BFS (level-order traversal) to visit nodes level by level. + // Stores "null" for missing children to maintain structure. + // Output format: "1,2,3,null,null,4,5" (comma-separated values). + + if (!root) return ""; + + let queue = [root]; + let str = []; + + while (queue.length > 0) { + let node = queue.shift(); + + if (node) { + str.push(node.val); + queue.push(node.left); + queue.push(node.right); + } else { + str.push("null"); + } + } + return str.join(","); +}; + +// ✅ Time Complexity: O(N), where N is the number of nodes +// ✅ Space Complexity: O(N) + +/** + * Decodes your encoded data to tree. + * + * @param {string} data + * @return {TreeNode} + */ +var deserialize = function (data) { + // Deserialization (String → Tree) + // Splits the serialized string into an array of values. + // Uses BFS (level-order traversal) to reconstruct the tree. + + if (!data) return null; + + let values = data.split(","); + let root = new TreeNode(parseInt(values[0])); // // Root node at index 0 + let queue = [root]; + let index = 1; // Start processing children from index 1 + + while (queue.length > 0) { + let node = queue.shift(); + + // Process left child (index points to left node value) + if (values[index] !== "null") { + node.left = new TreeNode(parseInt(values[index])); + queue.push(node.left); + } + + index += 1; // Move to the next position + + // Process right child (ensure index is within bounds) + if (index < values.length && values[index] !== "null") { + // Ensure we don't access an index out of bounds + node.right = new TreeNode(parseInt(values[index])); + queue.push(node.right); + } + + index += 1; // Move to the next position + } + + return root; +}; + +/** + * Your functions will be called as such: + * deserialize(serialize(root)); + */