From 7287a87a27865cf27cf252173ae8bb690da57913 Mon Sep 17 00:00:00 2001 From: jeehay Date: Mon, 13 Jan 2025 00:14:21 +0900 Subject: [PATCH 1/5] Add container-with-most-water solution --- container-with-most-water/Jeehay28.js | 29 +++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 container-with-most-water/Jeehay28.js diff --git a/container-with-most-water/Jeehay28.js b/container-with-most-water/Jeehay28.js new file mode 100644 index 000000000..fcdd4380f --- /dev/null +++ b/container-with-most-water/Jeehay28.js @@ -0,0 +1,29 @@ +/** + * @param {number[]} height + * @return {number} + */ + +// Time Complexity: O(n) +// Space Complexity: O(1) +var maxArea = function (height) { + let start = 0; + let end = height.length - 1; + let maxArea = 0; + + while (start < end) { + const area = (end - start) * Math.min(height[start], height[end]); + maxArea = Math.max(area, maxArea); + + // The shorter height limits the area. + // By moving the pointer associated with the shorter height, + // the algorithm maximizes the chance of finding a taller line that can increase the area. + // This is the essence of the two-pointer strategy for the container problem. + if (height[start] < height[end]) { + start += 1; + } else { + end -= 1; + } + } + return maxArea; +}; + From b2a6a85c35c26e3182fe30991d6d60f73c3f25c9 Mon Sep 17 00:00:00 2001 From: jeehay Date: Mon, 13 Jan 2025 00:16:49 +0900 Subject: [PATCH 2/5] Add valid-parentheses solution --- valid-parentheses/Jeehay28.js | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 valid-parentheses/Jeehay28.js diff --git a/valid-parentheses/Jeehay28.js b/valid-parentheses/Jeehay28.js new file mode 100644 index 000000000..4b6602dc9 --- /dev/null +++ b/valid-parentheses/Jeehay28.js @@ -0,0 +1,35 @@ +/** + * @param {string} s + * @return {boolean} + */ + +// Time Complexity: O(n) +// Space Complexity: O(n) +var isValid = function (s) { + const obj = { + "(" : ")", + "{" : "}", + "[" : "]", + }; + + let stack = []; + + for (any of s) { + // open bracket + if (obj[any]) { + stack.push(any); + } else { + // close bracket + if (stack.length === 0) { + return false; + } else if (obj[stack[stack.length - 1]] !== any) { + return false; + } else { + stack.pop(); + } + } + } + return stack.length === 0 ? true : false; +}; + + From 50b3ab9c74262d0d8199f820c8417e517715d526 Mon Sep 17 00:00:00 2001 From: jeehay Date: Sat, 18 Jan 2025 21:35:09 +0900 Subject: [PATCH 3/5] Add design-add-and-search-words-data-structure solution --- .../Jeehay28.js | 187 ++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 design-add-and-search-words-data-structure/Jeehay28.js diff --git a/design-add-and-search-words-data-structure/Jeehay28.js b/design-add-and-search-words-data-structure/Jeehay28.js new file mode 100644 index 000000000..c21027a8a --- /dev/null +++ b/design-add-and-search-words-data-structure/Jeehay28.js @@ -0,0 +1,187 @@ +/** + * ==================== Complexity Summary ==================== + * | Operation | Time Complexity | Space Complexity | + * |------------|------------------------|--------------------| + * | addWord | O(n) | O(n) | + * | search | O(n) (no '.') | O(n) | + * | | O(k^n) (with '.') | O(n) | + * ============================================================ + * + * Notes: + * - n: Length of the word being added/searched. + * - k: Average branching factor (number of children per node). + * - Worst-case time complexity for `search` with '.' can grow exponentially + * when many wildcards are present in the word. + */ + +var WordDictionary = function () { + this.root = { $: false }; +}; + +/** + * @param {string} word + * @return {void} + */ +WordDictionary.prototype.addWord = function (word) { + let node = this.root; + + for (char of word) { + if (!node[char]) { + node[char] = { $: false }; + } + node = node[char]; + } + + node["$"] = true; +}; + +/** + * @param {string} word + * @return {boolean} + */ +WordDictionary.prototype.search = function (word) { + const dfs = (node, index) => { + // Base case: If we've reached the end of the word + if (index === word.length) { + return node["$"] === true; + } + + const char = word[index]; + + // If the character is not a wildcard + if (char !== ".") { + if (node[char]) { + return dfs(node[char], index + 1); // Continue DFS + } else { + return false; // Character not found + } + } + + // If the character is a wildcard + for (const key of Object.keys(node).filter((key) => key !== "$")) { + if (dfs(node[key], index + 1)) { + return true; // Return true if any child path matches + } + // Why we need to check if the recursive call to dfs returns true or false: + // 1) Early termination of recursion when a match is found: + // - Once we find a valid match, there's no need to explore other branches. + // 2) Proper propagation of the result back up the recursion stack: + // - A valid match found in a deeper level of recursion needs to return true + // all the way back to the initial search call to indicate success. + } + + return false; // No paths matched for the wildcard + }; + + return dfs(this.root, 0); // Start DFS from the root node +}; + +/** + * Your WordDictionary object will be instantiated and called as such: + * var obj = new WordDictionary() + * obj.addWord(word) + * var param_2 = obj.search(word) + */ + +// ***** second trial ***** +// var WordDictionary = function () { +// this.root = { $: true }; +// }; + +// /** +// * @param {string} word +// * @return {void} +// */ +// WordDictionary.prototype.addWord = function (word) { +// const dfs = (node, index) => { +// // exit +// if (index === word.length) { +// node["$"] = true; +// return; +// } + +// // add . +// if (!node["."]) { +// node["."] = { $: false }; +// } +// dfs(node["."], index + 1); + +// // add each character +// const temp = word[index]; + +// if (!node[temp]) { +// node[temp] = { $: false }; +// } +// dfs(node[temp], index + 1); +// }; + +// dfs(this.root, 0); +// }; + +// /** +// * @param {string} word +// * @return {boolean} +// */ +// WordDictionary.prototype.search = function (word) { +// let node = this.root; + +// for (char of word) { +// if (!node[char]) { +// return false; +// } +// node = node[char]; +// } + +// return node["$"]; +// }; + +/** + * Your WordDictionary object will be instantiated and called as such: + * var obj = new WordDictionary() + * obj.addWord(word) + * var param_2 = obj.search(word) + */ + +// ***** first trial ***** +// var WordDictionary = function () { +// this.root = new Set(); +// }; + +// /** +// * @param {string} word +// * @return {void} +// */ +// WordDictionary.prototype.addWord = function (word) { +// this.root.add(word); +// }; + +// /** +// * @param {string} word +// * @return {boolean} +// */ +// WordDictionary.prototype.search = function (word) { +// if (this.root.size === 0) { +// return false; +// } else { +// for (dict of this.root) { +// if (dict.length === word.length) { +// const found = word +// .split("") +// .every((str, index) => str === "." || dict[index] === str); +// if (found) { +// return true; +// } +// } else { +// continue; +// } +// } +// return false; +// } +// }; + +/** + * Your WordDictionary object will be instantiated and called as such: + * var obj = new WordDictionary() + * obj.addWord(word) + * var param_2 = obj.search(word) + */ From b64d18b73421cdf8e338a25713f8ffe46b43c056 Mon Sep 17 00:00:00 2001 From: jeehay Date: Sat, 18 Jan 2025 23:07:24 +0900 Subject: [PATCH 4/5] Add spiral-matrix solution --- spiral-matrix/Jeehay28.js | 66 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 spiral-matrix/Jeehay28.js diff --git a/spiral-matrix/Jeehay28.js b/spiral-matrix/Jeehay28.js new file mode 100644 index 000000000..b1956d1fa --- /dev/null +++ b/spiral-matrix/Jeehay28.js @@ -0,0 +1,66 @@ +// Time Complexity: O(m * n), where m is the number of rows and n is the number of columns in the matrix, +// because every element is processed once. + +// Space Complexity: O(m * n), where m is the number of rows and n is the number of columns in the matrix, +// because we store all matrix elements in the result array. + +/** + * @param {number[][]} matrix + * @return {number[]} + */ +var spiralOrder = function (matrix) { + + let topRow = 0; + let bottomRow = matrix.length - 1; + let leftCol = 0; + let rightCol = matrix[0].length - 1; + let result = []; + + while (topRow <= bottomRow && leftCol <= rightCol) { + // move to the right + for (let col = leftCol; col <= rightCol; col++) { + result.push(matrix[topRow][col]); + } + + topRow += 1; + + if (topRow > bottomRow) { + break; + } + + // move down + for (let row = topRow; row <= bottomRow; row++) { + result.push(matrix[row][rightCol]); + } + + rightCol -= 1; + + if (leftCol > rightCol) { + break; + } + + // move to the left + for (let col = rightCol; col >= leftCol; col--) { + result.push(matrix[bottomRow][col]); + } + + bottomRow -= 1; + if (topRow > bottomRow) { + break; + } + + // move up + for (let row = bottomRow; row >= topRow; row--) { + result.push(matrix[row][leftCol]); + } + + leftCol += 1; + + if (leftCol > rightCol) { + break; + } + } + + return result; +}; + From ec041f9dbf978ed6b6ba836974e1a750b7319007 Mon Sep 17 00:00:00 2001 From: jeehay Date: Sun, 19 Jan 2025 01:55:05 +0900 Subject: [PATCH 5/5] Add longest-increasing-subsequence solution --- longest-increasing-subsequence/Jeehay28.js | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 longest-increasing-subsequence/Jeehay28.js diff --git a/longest-increasing-subsequence/Jeehay28.js b/longest-increasing-subsequence/Jeehay28.js new file mode 100644 index 000000000..c592e5c6b --- /dev/null +++ b/longest-increasing-subsequence/Jeehay28.js @@ -0,0 +1,26 @@ +/** + * @param {number[]} nums + * @return {number} + */ + +// Time Complexity: O(n^) +// Space Complexity: O(n) +var lengthOfLIS = function (nums) { + if (nums.length === 0) { + return 0; + } + + let dp = new Array(nums.length).fill(1); // dp[i] will be the length of LIS ending at i + + for (let i = 1; i < nums.length; i++) { + for (let j = 0; j < i; j++) { + if (nums[i] > nums[j]) { + // Strictly increasing condition + dp[i] = Math.max(dp[i], dp[j] + 1); + } + } + } + + return Math.max(...dp); // The length of the longest subsequence +}; +