From ff5acf14906063aab32509e3975c2f349c8b5d53 Mon Sep 17 00:00:00 2001 From: wogha95 Date: Sun, 1 Sep 2024 15:29:47 +0900 Subject: [PATCH 01/10] solve: valid palindrome --- valid-palindrome/wogha95.js | 82 +++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 valid-palindrome/wogha95.js diff --git a/valid-palindrome/wogha95.js b/valid-palindrome/wogha95.js new file mode 100644 index 000000000..069d4c168 --- /dev/null +++ b/valid-palindrome/wogha95.js @@ -0,0 +1,82 @@ +// 2차 +// TC: O(N) +// SC: O(N) +// N: s.length + +/** + * @param {string} s + * @return {boolean} + */ +var isPalindrome = function (s) { + const phrase = s.toLowerCase(); + // 1. 투포인터를 양끝에서 시작합니다. + let left = 0; + let right = phrase.length - 1; + + while (left < right) { + // 2. 현재 가리키는 문자가 영소문자, 숫자가 아니면 건너뜁니다. + while (left < right && !isValid(phrase[left])) { + left += 1; + } + while (left < right && !isValid(phrase[right])) { + right -= 1; + } + + // 3. 문자의 갯수가 홀수인 경우 투 포인터가 모두 가운데를 가리키는 경우 순회를 끝났다고 생각합니다. + if (left === right) { + break; + } + + // 4. 투 포인터가 가리키는 문자가 다른 경우 정답(false)를 반환합니다. + if (phrase[left] !== phrase[right]) { + return false; + } + + // 5. 다음 문자로 넘어갑니다. + left += 1; + right -= 1; + } + + // 6. 모든 순회가 끝냈다면 palindrome이라고 판단합니다. + return true; + + function isValid(spell) { + if ("0" <= spell && spell <= "9") { + return true; + } + if ("a" <= spell && spell <= "z") { + return true; + } + + return false; + } +}; + +// 1차 +// TC: O(N) +// SC: O(N) +// N: s.length + +/** + * @param {string} s + * @return {boolean} + */ +var isPalindrome = function (s) { + // 1. 문자열을 모두 소문자로 바꾸고 영소문자, 숫자만 남기고 모두 제거합니다. + const phrase = s + .toLowerCase() + .split("") + .filter( + (spell) => + ("0" <= spell && spell <= "9") || ("a" <= spell && spell <= "z") + ); + + // 2. 양끝의 문자를 확인해서 palindrome인지 판별합니다. + for (let index = 0; index < Math.floor(phrase.length / 2); index++) { + if (phrase[index] !== phrase[phrase.length - index - 1]) { + return false; + } + } + + return true; +}; From 77d6e59adf2995fcb7fd6d865bd80ba3835ef355 Mon Sep 17 00:00:00 2001 From: wogha95 Date: Sun, 1 Sep 2024 20:07:53 +0900 Subject: [PATCH 02/10] solve: missing number --- missing-number/wogha95.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 missing-number/wogha95.js diff --git a/missing-number/wogha95.js b/missing-number/wogha95.js new file mode 100644 index 000000000..442da4b4c --- /dev/null +++ b/missing-number/wogha95.js @@ -0,0 +1,21 @@ +// TC: O(N) +// SC: O(1) + +/** + * @param {number[]} nums + * @return {number} + */ +var missingNumber = function (nums) { + // result: subN - num의 누적합을 저장하는 변수 + let result = 0; + // subN: 1부터 N까지 올라가는 변수 + let subN = 1; + + for (const num of nums) { + result += subN - num; + subN += 1; + } + + // 최종 누적합은 (1~N까지 합) - (nums의 모든 원소 합) 이므로 누락된 숫자만 남게 됩니다. + return result; +}; From 5a921e55ff7a8c27612f69c918ef1191e9d6bddf Mon Sep 17 00:00:00 2001 From: wogha95 Date: Mon, 2 Sep 2024 22:33:15 +0900 Subject: [PATCH 03/10] solve: longest consecutive sequence --- longest-consecutive-sequence/wogha95.js | 41 +++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 longest-consecutive-sequence/wogha95.js diff --git a/longest-consecutive-sequence/wogha95.js b/longest-consecutive-sequence/wogha95.js new file mode 100644 index 000000000..971dccd29 --- /dev/null +++ b/longest-consecutive-sequence/wogha95.js @@ -0,0 +1,41 @@ +/** + * TC: O(N) + * SC: O(N) + * nums의 숫자에 접근하는 횟수는 2번에서 N만큼, 4번에서 최대 N만큼 입니다. + * 즉, 2N번 만큼 nums의 숫자에 접근합니다. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var longestConsecutive = function (nums) { + let maxCount = 0; + const obj = {}; + + // 1. 숫자의 존재 여부를 키로 접근하기 위해 저장 + for (const num of nums) { + obj[num] = true; + } + + // 2. 시작점들을 찾기 위해 순회 + for (const num of nums) { + // 3. 연속적인 배열의 시작점인지 확인 + if (obj[num - 1]) { + continue; + } + + // 4. 연속적인 배열의 시작점부터 끝점까지 순회 + let count = 1; + let next = num + 1; + while (obj[next]) { + count += 1; + next += 1; + } + + // 5. 가장 긴 배열의 길이 갱신 + maxCount = Math.max(maxCount, count); + } + + return maxCount; +}; From 15652ffa959f120913101d9de08657391a9e39ff Mon Sep 17 00:00:00 2001 From: wogha95 Date: Wed, 4 Sep 2024 21:06:33 +0900 Subject: [PATCH 04/10] solve: word search --- word-search/wogha95.js | 51 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 word-search/wogha95.js diff --git a/word-search/wogha95.js b/word-search/wogha95.js new file mode 100644 index 000000000..037027ad4 --- /dev/null +++ b/word-search/wogha95.js @@ -0,0 +1,51 @@ +// TC: O(M * N * 4^W) +// SC: O(MIN) +// W: word.length, MIN: min(M * N, W) + +/** + * @param {character[][]} board + * @param {string} word + * @return {boolean} + */ +var exist = function (board, word) { + let result = false; + + for (let r = 0; r < board.length; r++) { + for (let c = 0; c < board[0].length; c++) { + dfs(r, c, 0); + } + } + + return result; + + function dfs(row, column, wordIndex) { + if (!isValid(row, column)) { + return; + } + if (board[row][column] !== word[wordIndex]) { + return; + } + if (wordIndex === word.length - 1) { + result = true; + return; + } + + const temp = board[row][column]; + board[row][column] = "#"; + dfs(row + 1, column, wordIndex + 1); + dfs(row - 1, column, wordIndex + 1); + dfs(row, column + 1, wordIndex + 1); + dfs(row, column - 1, wordIndex + 1); + board[row][column] = temp; + } + + function isValid(row, column) { + if (row < 0 || board.length <= row) { + return false; + } + if (column < 0 || board[0].length <= column) { + return false; + } + return true; + } +}; From 918e6da0aa151946f250a1beb73b62a26c6dfdce Mon Sep 17 00:00:00 2001 From: wogha95 Date: Wed, 4 Sep 2024 22:18:56 +0900 Subject: [PATCH 05/10] solve: maximum product subarray --- maximum-product-subarray/wogha95.js | 39 +++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 maximum-product-subarray/wogha95.js diff --git a/maximum-product-subarray/wogha95.js b/maximum-product-subarray/wogha95.js new file mode 100644 index 000000000..f46d314f0 --- /dev/null +++ b/maximum-product-subarray/wogha95.js @@ -0,0 +1,39 @@ +// TC: O(N) +// SC: O(1) + +/** + * @param {number[]} nums + * @return {number} + */ +var maxProduct = function (nums) { + let maximumProduct = Number.MIN_SAFE_INTEGER; + let subProduct = 1; + // 1. 좌에서 우로 누적곱을 저장하기 위해 순회 + for (let index = 0; index < nums.length; index++) { + // 2. 0을 만나면 누적곱에 곱하지 않고 1로 초기화 + if (nums[index] === 0) { + maximumProduct = Math.max(maximumProduct, 0); + subProduct = 1; + continue; + } + // 3. 매번 누적곱을 갱신 + subProduct *= nums[index]; + maximumProduct = Math.max(maximumProduct, subProduct); + } + + subProduct = 1; + // 4. 우에서 좌로 누적곱을 저장하기 위해 순회 + for (let index = nums.length - 1; index >= 0; index--) { + // 5. 0을 만나면 누적곱에 곱하지 않고 1로 초기화 + if (nums[index] === 0) { + maximumProduct = Math.max(maximumProduct, 0); + subProduct = 1; + continue; + } + // 6. 매번 누적곱을 갱신 + subProduct *= nums[index]; + maximumProduct = Math.max(maximumProduct, subProduct); + } + + return maximumProduct; +}; From 3ff3afbdabe008e28dec7265036d9b91b46dc430 Mon Sep 17 00:00:00 2001 From: wogha95 Date: Wed, 4 Sep 2024 22:23:50 +0900 Subject: [PATCH 06/10] solve: word search --- word-search/wogha95.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/word-search/wogha95.js b/word-search/wogha95.js index 037027ad4..8bf41afa0 100644 --- a/word-search/wogha95.js +++ b/word-search/wogha95.js @@ -10,6 +10,7 @@ var exist = function (board, word) { let result = false; + // 1. 2차원 배열의 모든 좌표를 순회 for (let r = 0; r < board.length; r++) { for (let c = 0; c < board[0].length; c++) { dfs(r, c, 0); @@ -19,26 +20,33 @@ var exist = function (board, word) { return result; function dfs(row, column, wordIndex) { + // 2. 범위를 벗어난 좌표인지 검증 if (!isValid(row, column)) { return; } + // 3. word에서 찾고 있는 문자인지 확인 if (board[row][column] !== word[wordIndex]) { return; } + // 4. word 문자를 다 찾았는지 확인 if (wordIndex === word.length - 1) { result = true; return; } + // 5. 방문한 좌표를 표시하기 위해 다른 문자로 바꿔치기 해둠 const temp = board[row][column]; board[row][column] = "#"; + // 6. 상하좌우로 좌표 방문 dfs(row + 1, column, wordIndex + 1); dfs(row - 1, column, wordIndex + 1); dfs(row, column + 1, wordIndex + 1); dfs(row, column - 1, wordIndex + 1); + // 7. 해당 좌표의 재귀 방문이 끝나면 미방문으로 표시하기 위해 원래 문자로 되돌리기 board[row][column] = temp; } + // 유효한 좌표인지 확인하는 함수 function isValid(row, column) { if (row < 0 || board.length <= row) { return false; From 649b32c731978a2d39238598972894770bca8804 Mon Sep 17 00:00:00 2001 From: wogha95 Date: Fri, 6 Sep 2024 21:31:43 +0900 Subject: [PATCH 07/10] solve: word search --- word-search/wogha95.js | 62 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/word-search/wogha95.js b/word-search/wogha95.js index 8bf41afa0..0fee7db9b 100644 --- a/word-search/wogha95.js +++ b/word-search/wogha95.js @@ -1,3 +1,65 @@ +// 2차 +// result flag 변수를 활용 => boolean 반환으로 개선 +// TC: O(M * N * 4^W) +// SC: O(MIN) +// W: word.length, MIN: min(M * N, W) + +/** + * @param {character[][]} board + * @param {string} word + * @return {boolean} + */ +var exist = function (board, word) { + for (let r = 0; r < board.length; r++) { + for (let c = 0; c < board[0].length; c++) { + if (dfs(r, c, 0)) { + return true; + } + } + } + + return false; + + function dfs(row, column, wordIndex) { + if (!isValid(row, column)) { + return false; + } + if (board[row][column] !== word[wordIndex]) { + return false; + } + if (wordIndex === word.length - 1) { + return true; + } + + const temp = board[row][column]; + board[row][column] = "#"; + + if ( + dfs(row + 1, column, wordIndex + 1) || + dfs(row - 1, column, wordIndex + 1) || + dfs(row, column + 1, wordIndex + 1) || + dfs(row, column - 1, wordIndex + 1) + ) { + return true; + } + + board[row][column] = temp; + + return false; + } + + function isValid(row, column) { + if (row < 0 || board.length <= row) { + return false; + } + if (column < 0 || board[0].length <= column) { + return false; + } + return true; + } +}; + +// 1차 // TC: O(M * N * 4^W) // SC: O(MIN) // W: word.length, MIN: min(M * N, W) From 1f55061a8f431098803cedceaa57eac0a278f434 Mon Sep 17 00:00:00 2001 From: wogha95 Date: Fri, 6 Sep 2024 22:20:30 +0900 Subject: [PATCH 08/10] solve: longest consecutive sequence --- longest-consecutive-sequence/wogha95.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/longest-consecutive-sequence/wogha95.js b/longest-consecutive-sequence/wogha95.js index 971dccd29..db247bedd 100644 --- a/longest-consecutive-sequence/wogha95.js +++ b/longest-consecutive-sequence/wogha95.js @@ -3,6 +3,8 @@ * SC: O(N) * nums의 숫자에 접근하는 횟수는 2번에서 N만큼, 4번에서 최대 N만큼 입니다. * 즉, 2N번 만큼 nums의 숫자에 접근합니다. + * N^2이 아닌 이유: N^2이 아닌 2N으로 생각한 이유는 2번에서 N번의 순회를 하지만 각 순회가 서로에게 영향을 미치기 때문에 최대 순회는 2N으로 계산했습니다. (1번의 N 순회 제외) + * @see https://github.com/DaleStudy/leetcode-study/pull/408#discussion_r1747071917 */ /** From f1d5d77806722054b1b787103198c630cb5853b1 Mon Sep 17 00:00:00 2001 From: wogha95 Date: Sat, 7 Sep 2024 15:56:53 +0900 Subject: [PATCH 09/10] solve: valid palindrome --- valid-palindrome/wogha95.js | 67 +++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/valid-palindrome/wogha95.js b/valid-palindrome/wogha95.js index 069d4c168..d7527a701 100644 --- a/valid-palindrome/wogha95.js +++ b/valid-palindrome/wogha95.js @@ -1,3 +1,70 @@ +// 3차 +// TC: O(N) +// SC: O(N) +// N: s.length + +/** + * @param {string} s + * @return {boolean} + */ +var isPalindrome = function (s) { + // 1. 투포인터를 양끝에서 시작합니다. + let left = 0; + let right = s.length - 1; + + while (left < right) { + // 2. 현재 가리키는 문자가 영대소문자, 숫자가 아니면 건너뜁니다. + while (left < right && !isValid(s[left])) { + left += 1; + } + while (left < right && !isValid(s[right])) { + right -= 1; + } + + // 3. 문자의 갯수가 홀수인 경우 투 포인터가 모두 가운데를 가리키는 경우 순회를 끝났다고 생각합니다. + if (left === right) { + break; + } + + // 4. 투 포인터가 가리키는 문자가 다른 경우 정답(false)를 반환합니다. + if (!isSame(s[left], s[right])) { + return false; + } + + // 5. 다음 문자로 넘어갑니다. + left += 1; + right -= 1; + } + + // 6. 모든 순회가 끝냈다면 palindrome이라고 판단합니다. + return true; + + function isValid(spell) { + if ("0" <= spell && spell <= "9") { + return true; + } + if ("a" <= spell && spell <= "z") { + return true; + } + if ("A" <= spell && spell <= "Z") { + return true; + } + + return false; + } + + function isSame(spellA, spellB) { + if (spellA === spellB) { + return true; + } + if (Math.abs(s[left].charCodeAt() - s[right].charCodeAt()) === 32) { + return true; + } + + return false; + } +}; + // 2차 // TC: O(N) // SC: O(N) From 0975c1ce405548887ab807390477ce5bf8b5c4b1 Mon Sep 17 00:00:00 2001 From: wogha95 Date: Sat, 7 Sep 2024 15:57:51 +0900 Subject: [PATCH 10/10] solve: valid palindrome --- valid-palindrome/wogha95.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/valid-palindrome/wogha95.js b/valid-palindrome/wogha95.js index d7527a701..07de8d3a7 100644 --- a/valid-palindrome/wogha95.js +++ b/valid-palindrome/wogha95.js @@ -1,6 +1,6 @@ // 3차 // TC: O(N) -// SC: O(N) +// SC: O(1) // N: s.length /**