diff --git a/linked-list-cycle/Jeehay28.ts b/linked-list-cycle/Jeehay28.ts new file mode 100644 index 000000000..4e1a12822 --- /dev/null +++ b/linked-list-cycle/Jeehay28.ts @@ -0,0 +1,52 @@ +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) +// SC: O(1) +function hasCycle(head: ListNode | null): boolean { + + let fast: ListNode | null = head; + let slow: ListNode | null = head; + + while (fast && fast.next) { + fast = fast.next.next; + + if (slow !== null) { + slow = slow.next; + } else { + return false; + } + + if (fast === slow) return true; + } + + return false; +} + + +// TC: O(n) +// SC: O(n) +/* +function hasCycle(head: ListNode | null): boolean { + + let dummy: ListNode | null = head; + const visited = new Set(); + + while (dummy) { + if (visited.has(dummy)) return true; + + visited.add(dummy); + + dummy = dummy.next; + } + + return false; +} +*/ + diff --git a/maximum-product-subarray/Jeehay28.ts b/maximum-product-subarray/Jeehay28.ts new file mode 100644 index 000000000..8c367f0fe --- /dev/null +++ b/maximum-product-subarray/Jeehay28.ts @@ -0,0 +1,40 @@ +// TC: O(n) +// SC: O(1) +function maxProduct(nums: number[]): number { + let prevMax = nums[0]; + let prevMin = nums[0]; + let maxProd = nums[0]; + + for (let i = 1; i < nums.length; i++) { + const currentNum = nums[i]; + const tempMax = Math.max( + currentNum, + prevMax * currentNum, + prevMin * currentNum + ); + prevMin = Math.min(currentNum, prevMax * currentNum, prevMin * currentNum); + prevMax = tempMax; + maxProd = Math.max(maxProd, prevMax); + } + + return maxProd; +} + + +// TC: O(n^2) +// SC: O(1) +// function maxProduct(nums: number[]): number { +// let largestProd = -Infinity; +// let subProd = 1; + +// for (let i = 0; i < nums.length; i++) { +// subProd = 1; +// for (let j = i; j < nums.length; j++) { +// subProd *= nums[j]; +// largestProd = Math.max(largestProd, subProd); +// } +// } + +// return largestProd; +// } + diff --git a/minimum-window-substring/Jeehay28.ts b/minimum-window-substring/Jeehay28.ts new file mode 100644 index 000000000..cb588af1b --- /dev/null +++ b/minimum-window-substring/Jeehay28.ts @@ -0,0 +1,49 @@ +// TC: O(m+ n), where m is the length of s, and n is the length of t +// SC: O(n) + +function minWindow(s: string, t: string): string { + const tCnt = new Map(); + const windowCnt = new Map(); + + for (const ch of t) { + tCnt.set(ch, (tCnt.get(ch) || 0) + 1); + } + + let left = 0; + let validWindowKeySize = 0; + let minStrLength = Infinity; + let minLeft = 0; + + for (let right = 0; right < s.length; right++) { + const ch = s[right]; + + windowCnt.set(ch, (windowCnt.get(ch) || 0) + 1); + + if (tCnt.has(ch) && tCnt.get(ch) === windowCnt.get(ch)) { + validWindowKeySize++; + } + + // When windowCnt's keys include all the keys from tCnt + while (tCnt.size === validWindowKeySize && left <= right) { + // Update the minimum window details: start index (minLeft) and length (minStrLength) + if (right - left + 1 < minStrLength) { + minStrLength = right - left + 1; + minLeft = left; + } + + // shrink the window by moving the left pointer + const ch = s[left]; + windowCnt.set(ch, windowCnt.get(ch)! - 1); + + if (tCnt.has(ch) && windowCnt.get(ch)! < tCnt.get(ch)!) { + validWindowKeySize--; + } + + left++; + } + } + + return minStrLength === Infinity + ? "" + : s.slice(minLeft, minLeft + minStrLength); +} diff --git a/pacific-atlantic-water-flow/Jeehay28.ts b/pacific-atlantic-water-flow/Jeehay28.ts new file mode 100644 index 000000000..0faf7c39e --- /dev/null +++ b/pacific-atlantic-water-flow/Jeehay28.ts @@ -0,0 +1,71 @@ +// TC: O(m * n) +// SC: O(m * n) + +function pacificAtlantic(heights: number[][]): number[][] { + const m = heights.length; + const n = heights[0].length; + + const pacific: boolean[][] = Array.from({ length: m }, () => + Array(n).fill(false) + ); + const atlantic: boolean[][] = Array.from({ length: m }, () => + Array(n).fill(false) + ); + + const directions = [ + [0, 1], + [0, -1], + [1, 0], + [-1, 0], + ]; + + const dfs = (row: number, col: number, visited: boolean[][]) => { + visited[row][col] = true; + // Border cells are adjacent to the ocean, so they are marked as reachable (true) + + // From each ocean-border cell, we explore inward: + // if an adjacent cell is higher or equal, water can flow from it to the ocean + // → mark it as reachable (true) + for (const [dr, dc] of directions) { + const newRow = row + dr; + const newCol = col + dc; + + if ( + newRow >= 0 && + newRow < m && + newCol >= 0 && + newCol < n && + !visited[newRow][newCol] && + heights[row][col] <= heights[newRow][newCol] + // heights[row][col] <= heights[newRow][newCol] + // → Water can flow from (newRow, newCol) to (row, col), + // so (row, col) is reachable from the ocean through (newRow, newCol) + ) { + dfs(newRow, newCol, visited); + } + } + }; + + for (let i = 0; i < m; i++) { + dfs(i, 0, pacific); + dfs(i, n - 1, atlantic); + } + + for (let j = 0; j < n; j++) { + dfs(0, j, pacific); + dfs(m - 1, j, atlantic); + } + + let result: number[][] = []; + + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (pacific[i][j] && atlantic[i][j]) { + result.push([i, j]); + } + } + } + + return result; +} + diff --git a/sum-of-two-integers/Jeehay28.ts b/sum-of-two-integers/Jeehay28.ts new file mode 100644 index 000000000..8c72a1e3a --- /dev/null +++ b/sum-of-two-integers/Jeehay28.ts @@ -0,0 +1,12 @@ +// TC: O(1) +// SC: O(1) +function getSum(a: number, b: number): number { + while (b !== 0) { + let carry = a & b; + a = a ^ b; // sum WITHOUT the carry + b = carry << 1; // new carry + } + + return a; +} +