diff --git a/course-schedule/Jeehay28.ts b/course-schedule/Jeehay28.ts new file mode 100644 index 000000000..3ef3fc747 --- /dev/null +++ b/course-schedule/Jeehay28.ts @@ -0,0 +1,46 @@ +// TC: O(V + E), V = numCourses, E = prerequisites.length +// SC: O(V + E) + +function canFinish(numCourses: number, prerequisites: number[][]): boolean { + // 0: [1] + // 1: [] + + const graph = new Map(); + + // Initialize all courses + for (let i = 0; i < numCourses; i++) { + graph.set(i, []); + } + + // Build the graph + for (const [crs, pre] of prerequisites) { + graph.get(crs)!.push(pre); + } + + const traversing = new Set(); + const finished = new Set(); + + const dfs = (crs: number): boolean => { + if (traversing.has(crs)) return false; // cycle detected + + if (finished.has(crs)) return true; // already visited + + traversing.add(crs); + + for (const pre of graph.get(crs)!) { + if (!dfs(pre)) return false; + } + + traversing.delete(crs); + finished.add(crs); + + return true; + }; + + for (const crs of graph.keys()) { + if (!dfs(crs)) return false; + } + + return true; +} + diff --git a/invert-binary-tree/Jeehay28.ts b/invert-binary-tree/Jeehay28.ts new file mode 100644 index 000000000..ebde29f21 --- /dev/null +++ b/invert-binary-tree/Jeehay28.ts @@ -0,0 +1,62 @@ +class TreeNode { + val: number; + left: TreeNode | null; + right: TreeNode | null; + constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + this.val = val === undefined ? 0 : val; + this.left = left === undefined ? null : left; + this.right = right === undefined ? null : right; + } +} + +// TC: O(n) +// SC: O(n) +function invertTree(root: TreeNode | null): TreeNode | null { + if (!root) return null; + + const left = invertTree(root.right); + const right = invertTree(root.left); + + root.left = left; + root.right = right; + + return root; +} + + +// TC: O(n) +// SC: O(n) +// function invertTree(root: TreeNode | null): TreeNode | null { +// if (!root) return null; + +// [root.left, root.right] = [root.right, root.left]; + +// invertTree(root.left); +// invertTree(root.right); + +// return root; + +// } + + +// TC: O(n) +// SC: O(n) +// function invertTree(root: TreeNode | null): TreeNode | null { +// if (!root) return null; + +// const stack: (TreeNode | null)[] = [root]; + +// while (stack.length > 0) { +// const node = stack.pop(); + +// if (!node) continue; + +// [node.left, node.right] = [node.right, node.left]; + +// stack.push(node.left); +// stack.push(node.right); +// } + +// return root; +// } + diff --git a/jump-game/Jeehay28.ts b/jump-game/Jeehay28.ts new file mode 100644 index 000000000..2fb3abf2a --- /dev/null +++ b/jump-game/Jeehay28.ts @@ -0,0 +1,40 @@ +// TC: O(n) +// SC: O(1) +function canJump(nums: number[]): boolean { + // nums = [3, 2, 1, 0, 4] + // farthest 3, 3, 3, 3 + let farthest = 0; + + for (let i = 0; i < nums.length; i++) { + if (i > farthest) return false; + farthest = Math.max(farthest, nums[i] + i); + } + return true; +} + + +// ❌ TC: O(n^2) +// SC: O(n) + +// function canJump(nums: number[]): boolean { +// const lastIndex = nums.length - 1; +// const visited = new Map(); + +// const canReach = (current: number): boolean => { +// if (current === lastIndex) return true; + +// if (visited.has(current)) return visited.get(current) as boolean; + +// for (let i = 1; i <= nums[current]; i++) { +// if (current + i <= lastIndex) { +// if (canReach(current + i)) return true; +// } +// } + +// visited.set(current, false); + +// return false; +// }; + +// return canReach(0); +// } diff --git a/merge-k-sorted-lists/Jeehay28.ts b/merge-k-sorted-lists/Jeehay28.ts new file mode 100644 index 000000000..1a0a26fb5 --- /dev/null +++ b/merge-k-sorted-lists/Jeehay28.ts @@ -0,0 +1,37 @@ +class ListNode { + val: number; + next: ListNode | null; + constructor(val?: number, next?: ListNode | null) { + this.val = val === undefined ? 0 : val; + this.next = next === undefined ? null : next; + } +} + +// TC: O(n * log n), n = total number of all nodes combined (across all lists) +// SC: O(n) +// TDDO: Implement more optimized solution using Min Heap with TC: O(n log k) +function mergeKLists(lists: Array): ListNode | null { + const nodeValues: number[] = []; + + for (let node of lists) { + while (node) { + nodeValues.push(node.val); + node = node.next; + } + } + + nodeValues.sort((a, b) => a - b); + + if (nodeValues.length === 0) return null; + + const head = new ListNode(nodeValues[0]); + let temp = head; + + for (let i = 1; i < nodeValues.length; i++) { + temp.next = new ListNode(nodeValues[i]); + temp = temp.next; + } + + return head; +} + diff --git a/search-in-rotated-sorted-array/Jeehay28.ts b/search-in-rotated-sorted-array/Jeehay28.ts new file mode 100644 index 000000000..a39f7dc7e --- /dev/null +++ b/search-in-rotated-sorted-array/Jeehay28.ts @@ -0,0 +1,69 @@ +// TC: O(log n) +// SC: O(1) +function search(nums: number[], target: number): number { + let left = 0; + let right = nums.length - 1; + + while (left <= right) { + const mid = Math.floor((left + right) / 2); + + if (nums[mid] === target) return mid; + + if (nums[left] <= nums[mid]) { + // Left half is sorted + if (nums[left] <= target && target < nums[mid]) { + right = mid - 1; + } else { + left = mid + 1; + } + } else { + // Right half is sorted + if (nums[mid] < target && target <= nums[right]) { + left = mid + 1; + } else { + right = mid - 1; + } + } + } + + return -1; +} + +// TC: O(log n) +// SC: O(1) +// function search(nums: number[], target: number): number { +// const findPivot = (nums: number[]) => { +// let left = 0; +// let right = nums.length - 1; + +// while (left <= right) { +// const mid = Math.floor((left + right) / 2); +// if (mid > 0 && nums[mid - 1] > nums[mid]) return mid; +// if (nums[0] <= nums[mid]) { +// left = mid + 1; +// } else { +// right = mid - 1; +// } +// } +// return 0; +// }; + +// const binarySearch = (left: number, right: number) => { +// while (left <= right) { +// const mid = Math.floor((left + right) / 2); +// if (nums[mid] === target) return mid; +// if (nums[mid] < target) { +// left = mid + 1; +// } else { +// right = mid - 1; +// } +// } +// return -1; +// }; + +// const pivot = findPivot(nums); +// return Math.max( +// binarySearch(0, pivot - 1), +// binarySearch(pivot, nums.length - 1) +// ); +// }