From f7961c55e56c422973d03e23ff1495abe0063f1f Mon Sep 17 00:00:00 2001 From: wogha95 Date: Sun, 15 Sep 2024 15:21:59 +0900 Subject: [PATCH 1/7] solve: valid parentheses --- valid-parentheses/wogha95.js | 44 ++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 valid-parentheses/wogha95.js diff --git a/valid-parentheses/wogha95.js b/valid-parentheses/wogha95.js new file mode 100644 index 000000000..75a677dd2 --- /dev/null +++ b/valid-parentheses/wogha95.js @@ -0,0 +1,44 @@ +/** + * TC: O(S) + * s 매개변수의 길이만큼 순회 1번 + * + * SC: O(S) + * 최악의 경우 S의 길이만큼 stack 배열에 모두 push 할 수 있기 때문에 + * + * S: s.length + */ + +/** + * @param {string} s + * @return {boolean} + */ +var isValid = function (s) { + const map = { + "(": ")", + "{": "}", + "[": "]", + }; + const stack = []; + + // 1. s의 길이만큼 순회를 하면서 + for (const char of s) { + // 2. 열린 괄호라면 stack에 짝지어진 닫힌 괄호를 저장 + // 3. 닫힌 괄호라면 stack에서 꺼낸 것과 동일한지 확인 + switch (char) { + case "(": + case "{": + case "[": + stack.push(map[char]); + break; + case "}": + case ")": + case "]": + if (stack.pop() !== char) { + return false; + } + } + } + + // 4. 남은 괄호가 없는지 확인 + return stack.length === 0; +}; From b80c227c1d3811d7d260c0f2d3be8d504db7019b Mon Sep 17 00:00:00 2001 From: wogha95 Date: Sun, 15 Sep 2024 15:43:10 +0900 Subject: [PATCH 2/7] solve: container with most water --- container-with-most-water/wogha95.js | 33 ++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 container-with-most-water/wogha95.js diff --git a/container-with-most-water/wogha95.js b/container-with-most-water/wogha95.js new file mode 100644 index 000000000..86e6672bf --- /dev/null +++ b/container-with-most-water/wogha95.js @@ -0,0 +1,33 @@ +/** + * TC: O(H) + * SC: O(1) + * H: height.length + */ + +/** + * @param {number[]} height + * @return {number} + */ +var maxArea = function (height) { + let maximumWater = 0; + let left = 0; + let right = height.length - 1; + + // 1. 투포인터를 이용하여 양끝에서 모입니다. + while (left < right) { + // 2. 최대 너비값을 갱신해주고 + const h = Math.min(height[left], height[right]); + const w = right - left; + + maximumWater = Math.max(maximumWater, w * h); + + // 3. 왼쪽과 오른쪽 높이 중 더 낮은 쪽의 pointer를 옮깁니다. + if (height[left] < height[right]) { + left += 1; + } else { + right -= 1; + } + } + + return maximumWater; +}; From 5fcfcef3f4da07d13c52149a973d8414cbd0b493 Mon Sep 17 00:00:00 2001 From: wogha95 Date: Sun, 15 Sep 2024 18:24:55 +0900 Subject: [PATCH 3/7] solve: spiral matrix --- spiral-matrix/wogha95.js | 140 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 spiral-matrix/wogha95.js diff --git a/spiral-matrix/wogha95.js b/spiral-matrix/wogha95.js new file mode 100644 index 000000000..487260c76 --- /dev/null +++ b/spiral-matrix/wogha95.js @@ -0,0 +1,140 @@ +/** + * 2차 풀이: 기존 matrix 변경 없도록 개선 + * + * TC: O(ROW * COLUMN) + * matrix 전체 순회 1회 + * + * SC: O(ROW * COLUMN) + * 정답 제출을 위한 result 공간복잡도 + */ + +/** + * @param {number[][]} matrix + * @return {number[]} + */ +var spiralOrder = function (matrix) { + const ROW = matrix.length; + const COLUMN = matrix[0].length; + // 1. 상하좌우 시작끝 index를 저장함 + const boundary = { + top: 0, + bottom: ROW - 1, + left: 0, + right: COLUMN - 1, + }; + const result = []; + + while (result.length < ROW * COLUMN) { + // 2. 오른쪽으로 순회 + for (let column = boundary.left; column <= boundary.right; column++) { + result.push(matrix[boundary.top][column]); + } + boundary.top += 1; + + // 3. 아래로 순회 + for (let row = boundary.top; row <= boundary.bottom; row++) { + result.push(matrix[row][boundary.right]); + } + boundary.right -= 1; + + // 4. 모두 순회했는데 왔던길 되돌아가는 경우를 막기위해 중간 조건문 추가 + if (result.length === ROW * COLUMN) { + break; + } + + // 5. 왼쪽으로 순회 + for (let column = boundary.right; column >= boundary.left; column--) { + result.push(matrix[boundary.bottom][column]); + } + boundary.bottom -= 1; + + // 6. 위쪽으로 순회 + for (let row = boundary.bottom; row >= boundary.top; row--) { + result.push(matrix[row][boundary.left]); + } + boundary.left += 1; + } + + return result; +}; + +/** + * 1차 풀이 + * + * TC: O(ROW * COLUMN) + * matrix 전체 순회 1회 + * + * SC: O(ROW * COLUMN) + * 정답 제출을 위한 result 공간복잡도 + */ + +/** + * @param {number[][]} matrix + * @return {number[]} + */ +var spiralOrder = function (matrix) { + const ROW = matrix.length; + const COLUMN = matrix[0].length; + // 우하좌상 순서 + const DIRECTION = [ + { + row: 0, + column: 1, + }, + { + row: 1, + column: 0, + }, + { + row: 0, + column: -1, + }, + { + row: -1, + column: 0, + }, + ]; + + // 1. 첫 시작점 방문표시 + const result = [matrix[0][0]]; + matrix[0][0] = "#"; + + let current = { + row: 0, + column: 0, + }; + let directionIndex = 0; + + // 2. 총 갯수만큼 채워질때까지 순회 + while (result.length < ROW * COLUMN) { + const next = { + row: current.row + DIRECTION[directionIndex].row, + column: current.column + DIRECTION[directionIndex].column, + }; + // 3. 다음 순회할 곳이 유효한 좌표인지 방문한 곳인지 확인 + if ( + !isValidPosition(next.row, next.column) || + matrix[next.row][next.column] === "#" + ) { + // 4. 방향 전환 + directionIndex = (directionIndex + 1) % 4; + } else { + // 5. 방문 표시 후 다음 좌표로 이동 + result.push(matrix[next.row][next.column]); + matrix[next.row][next.column] = "#"; + current = next; + } + } + + return result; + + function isValidPosition(row, column) { + if (row < 0 || ROW <= row) { + return false; + } + if (column < 0 || COLUMN <= column) { + return false; + } + return true; + } +}; From 9f452a9fae9ce45656610e972bbddf47fd7cdc17 Mon Sep 17 00:00:00 2001 From: wogha95 Date: Wed, 18 Sep 2024 13:12:00 +0900 Subject: [PATCH 4/7] solve: design add and search words data structure --- .../wogha95.js | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 design-add-and-search-words-data-structure/wogha95.js diff --git a/design-add-and-search-words-data-structure/wogha95.js b/design-add-and-search-words-data-structure/wogha95.js new file mode 100644 index 000000000..4061fba59 --- /dev/null +++ b/design-add-and-search-words-data-structure/wogha95.js @@ -0,0 +1,83 @@ +function Node() { + // 단어의 끝을 의미 + 무슨 단어인지 저장 + this.value = null; + // 단어의 다음 문자로 연결되어 있는 노드맵 + this.wordGraph = new Map(); +} + +var WordDictionary = function () { + this.wordGraph = new Map(); +}; + +/** + * TC: O(N) + * SC: O(1) + */ + +/** + * @param {string} word + * @return {void} + */ +WordDictionary.prototype.addWord = function (word) { + let pointer = this; + for (const w of word) { + if (!pointer.wordGraph.has(w)) { + pointer.wordGraph.set(w, new Node()); + } + pointer = pointer.wordGraph.get(w); + } + pointer.value = word; +}; + +/** + * TC: O(D^W) + * SC: O(D * W) + * + * W: word.length, D: count of Dictionary.wordGraph keys + * + * 풀이: Trie 자료구조 + bfs탐색 + */ + +/** + * @param {string} word + * @return {boolean} + */ +WordDictionary.prototype.search = function (word) { + const queue = [{ pointer: this, index: 0 }]; + + // 1. BFS 탐색 방법 이용 + while (queue.length > 0) { + const { pointer, index } = queue.shift(); + + // 2. 찾고자하는 단어의 끝에 도달했으면 해당 단어가 있는지 확인한다. + if (index === word.length) { + if (pointer.value !== null) { + return true; + } + continue; + } + + if (word[index] === ".") { + // 3. 찾고자하는 단어의 문자가 '.'인 경우, 현재 graph에서 이어진 문자를 모두 탐색(queue에 추가) + for (const [key, node] of pointer.wordGraph) { + queue.push({ pointer: node, index: index + 1 }); + } + } else if (pointer.wordGraph.has(word[index])) { + // 4. 찾고자하는 단어의 문자가 graph에 있는 경우 탐색(queue에 추가) + queue.push({ + pointer: pointer.wordGraph.get(word[index]), + index: index + 1, + }); + } + } + + // 5. 더이상 탐색할 것이 없다면 해당 단어 없음으로 판단 + 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 e1c705d41e8d402ce04c4545d74377b523395a7a Mon Sep 17 00:00:00 2001 From: wogha95 Date: Wed, 18 Sep 2024 14:07:03 +0900 Subject: [PATCH 5/7] solve: longest increasing subsequence --- longest-increasing-subsequence/wogha95.js | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 longest-increasing-subsequence/wogha95.js diff --git a/longest-increasing-subsequence/wogha95.js b/longest-increasing-subsequence/wogha95.js new file mode 100644 index 000000000..6a60b28d2 --- /dev/null +++ b/longest-increasing-subsequence/wogha95.js @@ -0,0 +1,28 @@ +/** + * TC: O(N^2) + * SC: O(N) + * N: nums.length + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var lengthOfLIS = function (nums) { + // 각자 스스로는 최소 1의 lengthOfLIS를 가짐 + const longestLength = new Array(nums.length).fill(1); + + // nums배열의 right까지 원소들 중 lengthOfLIS를 저장 + for (let right = 1; right < nums.length; right++) { + for (let left = 0; left < right; left++) { + if (nums[left] < nums[right]) { + longestLength[right] = Math.max( + longestLength[right], + longestLength[left] + 1 + ); + } + } + } + + return Math.max(...longestLength); +}; From 7f57e00cd8a1c3f1ccc622e5471587bad4b65eae Mon Sep 17 00:00:00 2001 From: wogha95 Date: Sat, 21 Sep 2024 17:31:25 +0900 Subject: [PATCH 6/7] solve: design add and search words data structure --- design-add-and-search-words-data-structure/wogha95.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/design-add-and-search-words-data-structure/wogha95.js b/design-add-and-search-words-data-structure/wogha95.js index 4061fba59..3023320cd 100644 --- a/design-add-and-search-words-data-structure/wogha95.js +++ b/design-add-and-search-words-data-structure/wogha95.js @@ -11,7 +11,7 @@ var WordDictionary = function () { /** * TC: O(N) - * SC: O(1) + * SC: O(N) */ /** From e8f521cc6c4beec68328793c7277eea07392a487 Mon Sep 17 00:00:00 2001 From: wogha95 Date: Sat, 21 Sep 2024 17:35:52 +0900 Subject: [PATCH 7/7] solve: longest increasing subsequence --- longest-increasing-subsequence/wogha95.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/longest-increasing-subsequence/wogha95.js b/longest-increasing-subsequence/wogha95.js index 6a60b28d2..18d1c0103 100644 --- a/longest-increasing-subsequence/wogha95.js +++ b/longest-increasing-subsequence/wogha95.js @@ -11,6 +11,7 @@ var lengthOfLIS = function (nums) { // 각자 스스로는 최소 1의 lengthOfLIS를 가짐 const longestLength = new Array(nums.length).fill(1); + let result = 1; // nums배열의 right까지 원소들 중 lengthOfLIS를 저장 for (let right = 1; right < nums.length; right++) { @@ -20,9 +21,10 @@ var lengthOfLIS = function (nums) { longestLength[right], longestLength[left] + 1 ); + result = Math.max(result, longestLength[right]); } } } - return Math.max(...longestLength); + return result; };