From 356b9dea7b06b935a2de9d57fb5068dfac5f41ff Mon Sep 17 00:00:00 2001 From: jeehay Date: Mon, 20 Jan 2025 23:29:33 +0900 Subject: [PATCH 1/6] Add reverse-linked-list solution --- reverse-linked-list/Jeehay28.js | 82 +++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 reverse-linked-list/Jeehay28.js diff --git a/reverse-linked-list/Jeehay28.js b/reverse-linked-list/Jeehay28.js new file mode 100644 index 000000000..5d4c43cef --- /dev/null +++ b/reverse-linked-list/Jeehay28.js @@ -0,0 +1,82 @@ +/** + * Definition for singly-linked list. + * function ListNode(val, next) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + */ +/** + * @param {ListNode} head + * @return {ListNode} + */ + +// Time Complexity: O(n) +// Space Complexity: O(1) + +// The algorithm uses a constant amount of extra space: prev, current, and nextTemp. +// No additional data structures (like arrays or new linked lists) are created. +// Hence, the space complexity is O(1). + +var reverseList = function (head) { + let prev = null; + let current = head; + + while (current) { + let nextTemp = current.next; + + current.next = prev; + console.log(current, prev); + + prev = current; + console.log(current, prev); + current = nextTemp; + } + + return prev; // New head of the reversed list +}; + +// head = [1,2,3,4,5] +// [1] null +// [1] [1] +// [2,1] [1] +// [2,1] [2,1] +// [3,2,1] [2,1] +// [3,2,1] [3,2,1] +// [4,3,2,1] [3,2,1] +// [4,3,2,1] [4,3,2,1] +// [5,4,3,2,1] [5,4,3,2,1] + +// my own approach +// Time Complexity: O(n) +// Space Complexity: O(n) +var reverseList = function (head) { + if (head === null) { + return null; + } + + let current = head; + let arr = []; + // console.log(head.val) + + // traverse the linked List - TC: O(n) + while (current) { + arr.push(current.val); + current = current.next; + } + + // reverse the array - TC: O(n) + arr = arr.reverse(); + + let head1 = new ListNode(arr[0]); + let current1 = head1; + + // rebuild the linked list - TC: O(n) + for (let i = 1; i < arr.length; i++) { + current1.next = new ListNode(arr[i]); + current1 = current1.next; + } + + return head1; +}; + + From 4218a1bb1c4c6980cda4a2db5ec68914b51cf0b0 Mon Sep 17 00:00:00 2001 From: jeehay Date: Thu, 23 Jan 2025 00:56:36 +0900 Subject: [PATCH 2/6] Add longest-substring-without-repeating-characters solution --- .../Jeehay28.js | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 longest-substring-without-repeating-characters/Jeehay28.js diff --git a/longest-substring-without-repeating-characters/Jeehay28.js b/longest-substring-without-repeating-characters/Jeehay28.js new file mode 100644 index 000000000..60536cf6a --- /dev/null +++ b/longest-substring-without-repeating-characters/Jeehay28.js @@ -0,0 +1,64 @@ +/** + * @param {string} s + * @return {number} + */ + +// 🌟 sliding window technique + +// Time Complexity: O(n) +// Why it's O(n) +// - The end pointer iterates over the string exactly once (O(n)). +// - The start pointer also only moves forward without re-processing elements (O(n)). +// - Therefore, the total amount of work done is proportional to the length of the string (n). +// - So, even though there is a while loop inside the for loop, the total work done (number of operations) is still linear, O(n), because the start and end pointers together move across the string just once. +// - This is the key reason why the time complexity is O(n), even with nested loops. + +// Space Complexity: O(k), where k k is the length of the longest substring without repeating characters. +// In the worst case, k = n, so O(n) + +var lengthOfLongestSubstring = function (s) { + let start = 0; + let longest = 0; + let subString = new Set(); + + for (let end = 0; end < s.length; end++) { + while (subString.has(s[end])) { + // Shrink the window by moving start + subString.delete(s[start]); + start += 1; + } + + subString.add(s[end]); + longest = Math.max(longest, end - start + 1); + } + + return longest; +}; + +// 🛠️ Solution 1 +// Time Complexity: O(n^2), where n is the length of the string s +// Space Complexity: O(k), where k is the length of the longest substring without repeating characters (k ≤ n) + +// why the space complexity is not just O(n): +// - Saying O(n) is technically correct in the worst case, +// - but it hides the fact that the actual space usage is proportional to the length of the longest substring without repeats, +// - which could be much smaller than n in many practical cases (e.g., for a string like "aaabbbccc"). + +// var lengthOfLongestSubstring = function (s) { +// let longest = 0; + +// for (let i = 0; i < s.length; i++) { +// let subString = new Set(); + +// for (let j = i; j < s.length; j++) { +// if (subString.has(s[j])) { +// break; +// } else { +// subString.add(s[j]); +// longest = Math.max(longest, j - i + 1); +// } +// } +// } +// return longest; +// }; + From 0563971c2eb306d151d537dbcb4051cd026d6db1 Mon Sep 17 00:00:00 2001 From: jeehay Date: Fri, 24 Jan 2025 23:29:01 +0900 Subject: [PATCH 3/6] Add number-of-islands solution --- number-of-islands/Jeehay28.js | 50 +++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 number-of-islands/Jeehay28.js diff --git a/number-of-islands/Jeehay28.js b/number-of-islands/Jeehay28.js new file mode 100644 index 000000000..b7d07b926 --- /dev/null +++ b/number-of-islands/Jeehay28.js @@ -0,0 +1,50 @@ +/** + * @param {character[][]} grid + * @return {number} + */ + +// 🌻 +// Time Complexity: O(m * n), where M is the number of rows and N is the number of columns in the grid. +// Space Complexity: O(k), where k is the size of the largest island (k <= m * n) + +// The space complexity is determined by the depth of the recursive stack used by the sink function. +// In the worst-case scenario, where the entire grid is filled with "1"s (a single large island), +// the depth of recursion could go up to O(m * n). + +var numIslands = function (grid) { + // depth-first search (DFS) that potentially visits every connected cell in the current island + const sink = (row, col) => { + grid[row][col] = "0"; + + const adjacent = [ + [row - 1, col], // up + [row + 1, col], // down + [row, col - 1], // left + [row, col + 1], // right + ]; + + for ([r, c] of adjacent) { + if (r >= 0 && r < grid.length && c >= 0 && c < grid[r].length) { + if (grid[r][c] === "1") { + sink(r, c); + } + } + } + }; + + let cnt = 0; + + for (let i = 0; i < grid.length; i++) { + for (let j = 0; j < grid[0].length; j++) { + if (grid[i][j] === "1") { + cnt += 1; + sink(i, j); + } + } + } + + return cnt; +}; + + + From a84da2f8ddf71b4b4b5040c13792254bc3571372 Mon Sep 17 00:00:00 2001 From: jeehay Date: Sat, 25 Jan 2025 17:43:24 +0900 Subject: [PATCH 4/6] Add unique-paths solution --- unique-paths/Jeehay28.js | 86 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 unique-paths/Jeehay28.js diff --git a/unique-paths/Jeehay28.js b/unique-paths/Jeehay28.js new file mode 100644 index 000000000..069eb6716 --- /dev/null +++ b/unique-paths/Jeehay28.js @@ -0,0 +1,86 @@ +/** + * @param {number} m + * @param {number} n + * @return {number} + */ + +// 🍎 DP +// Time Complexity: O(m*n) +// Space Complexity: O(n) + +// Row 0: [1, 1, 1, 1] +// Row 1: [1, 2, 3, 4] +// Row 2: [1, 3, 6, 10] + +// Initial dp: [1, 1, 1, 1] +// left = 1 (always starts with 1 for the first column) + +// col = 1: left += dp[1] → left = 1 + 1 = 2 → dp[1] = left +// col = 2: left += dp[2] → left = 2 + 1 = 3 → dp[2] = left +// col = 3: left += dp[3] → left = 3 + 1 = 4 → dp[3] = left + +// dp after row 1: [1, 2, 3, 4] + +// Initial dp: [1, 2, 3, 4] +// left = 1 + +// col = 1: left += dp[1] → left = 1 + 2 = 3 → dp[1] = left +// col = 2: left += dp[2] → left = 3 + 3 = 6 → dp[2] = left +// col = 3: left += dp[3] → left = 6 + 4 = 10 → dp[3] = left + +// dp after row 2: [1, 3, 6, 10] + +var uniquePaths = function (m, n) { + let dp = new Array(n).fill(1); + + for (let row = 1; row < m; row++) { + let left = 1; + for (let col = 1; col < n; col++) { + left += dp[col]; + dp[col] = left; + } + } + + return dp[n - 1]; +}; + +/** + * @param {number} m + * @param {number} n + * @return {number} + */ + +// 🍎 DFS +// Time Complexity: O(m*n) +// Space Complexity: O(m*n) + +// var uniquePaths = function (m, n) { +// const memo = {}; + +// const dfs = (row, col) => { +// if (row === m - 1 && col === n - 1) { +// return 1; +// } + +// let cnt = 0; + +// const key = `${row}, ${col}`; +// if (key in memo) { +// return memo[key]; +// } + +// if (row + 1 < m) { +// cnt += dfs(row + 1, col); +// } + +// if (col + 1 < n) { +// cnt += dfs(row, col + 1); +// } + +// memo[key] = cnt; + +// return cnt; +// }; + +// return dfs(0, 0); +// }; From 4699e1d1b510710e71dc84b72c7ad663981eaf9c Mon Sep 17 00:00:00 2001 From: jeehay Date: Sat, 25 Jan 2025 20:07:57 +0900 Subject: [PATCH 5/6] Add set-matrix-zeroes solution --- set-matrix-zeroes/Jeehay28.js | 106 ++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 set-matrix-zeroes/Jeehay28.js diff --git a/set-matrix-zeroes/Jeehay28.js b/set-matrix-zeroes/Jeehay28.js new file mode 100644 index 000000000..b67876575 --- /dev/null +++ b/set-matrix-zeroes/Jeehay28.js @@ -0,0 +1,106 @@ +// 🌈 In-Place Solution (Without extra space) +// The term "in-place" refers to algorithms or solutions that modify the input data directly, +// without needing extra space for a separate copy of the data. In an in-place solution, +// the operations are performed using a fixed amount of extra memory, typically O(1) space, beyond the input data itself. + +/** + * @param {number[][]} matrix + * @return {void} Do not return anything, modify matrix in-place instead. + */ + +// Time Complexity: O(m * n) +// Space Complexity: O(1) +var setZeroes = function (matrix) { + const rows = matrix.length; + const cols = matrix[0].length; + + let firstRowHasZero = false; + let firstColHasZero = false; + + // Check if the first row has any zero + for (let c = 0; c < cols; c++) { + if (matrix[0][c] === 0) { + firstRowHasZero = true; + break; + } + } + + // Check if the first column has any zero + for (let r = 0; r < rows; r++) { + if (matrix[r][0] === 0) { + firstColHasZero = true; + break; + } + } + + // Use first row and column to mark zeros + for (let i = 1; i < rows; i++) { + for (let j = 1; j < cols; j++) { + if (matrix[i][j] === 0) { + matrix[0][j] = 0; + matrix[i][0] = 0; + } + } + } + + // Set zeros based on marks in the first row and column + for (let i = 1; i < rows; i++) { + for (let j = 1; j < cols; j++) { + if (matrix[0][j] === 0 || matrix[i][0] === 0) { + matrix[i][j] = 0; + } + } + } + + // Handle first row + if (firstRowHasZero) { + for (let c = 0; c < cols; c++) { + matrix[0][c] = 0; + } + } + + // Handle first column + if (firstColHasZero) { + for (let r = 0; r < rows; r++) { + matrix[r][0] = 0; + } + } + + return matrix; +}; + +/** + * @param {number[][]} matrix + * @return {void} Do not return anything, modify matrix in-place instead. + */ + +// 💪 My initial approach with Set... +// Time Complexity: O(m * n) +// Space Complexity: O(m + n) +var setZeroes = function (matrix) { + let rows = new Set(); + let cols = new Set(); + + for (let i = 0; i < matrix.length; i++) { + for (let j = 0; j < matrix[0].length; j++) { + if (matrix[i][j] === 0) { + rows.add(i); + cols.add(j); + } + } + } + + for (row of rows) { + matrix[row] = new Array(matrix[0].length).fill(0); + } + + for (col of cols) { + for (let row = 0; row < matrix.length; row++) { + matrix[row][col] = 0; + } + } + + return matrix; +}; + + From b49316a465c5c9e49f68ab4d1e8e4ffc75d59048 Mon Sep 17 00:00:00 2001 From: jeehay Date: Sat, 25 Jan 2025 20:10:25 +0900 Subject: [PATCH 6/6] Comment out the my initial approach --- set-matrix-zeroes/Jeehay28.js | 50 +++++++++++++++++------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/set-matrix-zeroes/Jeehay28.js b/set-matrix-zeroes/Jeehay28.js index b67876575..367edeba2 100644 --- a/set-matrix-zeroes/Jeehay28.js +++ b/set-matrix-zeroes/Jeehay28.js @@ -77,30 +77,30 @@ var setZeroes = function (matrix) { // 💪 My initial approach with Set... // Time Complexity: O(m * n) // Space Complexity: O(m + n) -var setZeroes = function (matrix) { - let rows = new Set(); - let cols = new Set(); - - for (let i = 0; i < matrix.length; i++) { - for (let j = 0; j < matrix[0].length; j++) { - if (matrix[i][j] === 0) { - rows.add(i); - cols.add(j); - } - } - } - - for (row of rows) { - matrix[row] = new Array(matrix[0].length).fill(0); - } - - for (col of cols) { - for (let row = 0; row < matrix.length; row++) { - matrix[row][col] = 0; - } - } - - return matrix; -}; +// var setZeroes = function (matrix) { +// let rows = new Set(); +// let cols = new Set(); + +// for (let i = 0; i < matrix.length; i++) { +// for (let j = 0; j < matrix[0].length; j++) { +// if (matrix[i][j] === 0) { +// rows.add(i); +// cols.add(j); +// } +// } +// } + +// for (row of rows) { +// matrix[row] = new Array(matrix[0].length).fill(0); +// } + +// for (col of cols) { +// for (let row = 0; row < matrix.length; row++) { +// matrix[row][col] = 0; +// } +// } + +// return matrix; +// };