From ff3b4088704637d986e7f779d91d10f5199705d1 Mon Sep 17 00:00:00 2001 From: eprnf Date: Thu, 12 Sep 2024 22:02:02 +0900 Subject: [PATCH 01/49] add readme --- oris8/README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 oris8/README.md diff --git a/oris8/README.md b/oris8/README.md new file mode 100644 index 0000000..e69de29 From 93d1ee5fdc5d5d4ad9995db5d47baee20c86b8b7 Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 24 Sep 2024 19:21:18 +0900 Subject: [PATCH 02/49] 217 / Contains Duplicate / easy / 2m 54s --- oris8/217_contains-duplicate.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 oris8/217_contains-duplicate.js diff --git a/oris8/217_contains-duplicate.js b/oris8/217_contains-duplicate.js new file mode 100644 index 0000000..789eb33 --- /dev/null +++ b/oris8/217_contains-duplicate.js @@ -0,0 +1,17 @@ +/** + * 2m 54s + * 정수 배열 번호가 주어지면 배열에 두 번 이상 표시되는 값이 있으면 참으로 반환하고, + * 모든 요소가 구분되는 경우 거짓으로 반환합니다. + * + * @param {number[]} nums + * @return {boolean} + */ +const containsDuplicate = (nums) => { + const bucket = new Set(); + + nums.forEach((num) => { + bucket.add(num); + }); + + return nums.length !== bucket.size; +}; From b3f351614543271a3363ae754e597bc9c4af5454 Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 24 Sep 2024 19:28:56 +0900 Subject: [PATCH 03/49] 268 / Missing Number / easy / 3m 15s --- oris8/268_missing-number.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 oris8/268_missing-number.js diff --git a/oris8/268_missing-number.js b/oris8/268_missing-number.js new file mode 100644 index 0000000..cfe6e74 --- /dev/null +++ b/oris8/268_missing-number.js @@ -0,0 +1,14 @@ +/** + * 3m 15s + * [0, n] 범위에 n개의 고유 숫자가 포함된 배열 번호가 주어지면 배열에서 누락된 범위의 유일한 숫자를 반환합니다. + * + * @param {number[]} nums + * @return {number} + */ +const missingNumber = (nums) => { + const lastNumber = nums.length; + + for (let i = 0; i <= lastNumber; i++) { + if (!nums.includes(i)) return i; + } +}; From a096dc41c352ef3a7d5feee57140040b260c40be Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 24 Sep 2024 19:39:02 +0900 Subject: [PATCH 04/49] 121 / Best Time to Buy and Sell Stock / easy / 15m 31s --- oris8/121_best-time-to-buy-and-sell-stock.js | 24 ++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 oris8/121_best-time-to-buy-and-sell-stock.js diff --git a/oris8/121_best-time-to-buy-and-sell-stock.js b/oris8/121_best-time-to-buy-and-sell-stock.js new file mode 100644 index 0000000..91dac21 --- /dev/null +++ b/oris8/121_best-time-to-buy-and-sell-stock.js @@ -0,0 +1,24 @@ +/** + * 15m 31s + * 한 번의 매수와 한 번의 매도로 얻을 수 있는 최대 수익 + * 수익을 얻을 수 없다면 0을 return + * + * @param {number[]} prices - i번째 날의 가격[i]이 주어진 주식의 가격들의 배열 + * @return {number} + */ +const maxProfit = (prices) => { + // minPrice를 업데이트해주고, + // minPrice에 따른 profit의 최댓값을 다시 업데이트 + let maximum = 0; + let minPrice = prices[0]; + for (price of prices) { + if (price < minPrice) { + minPrice = price; + } + maximum = Math.max(price - minPrice, maximum); + } + return maximum; +}; + +// Runtime: 61 ms Beats 96.30% +// Memory: 60.24MB Beats 11.54% From 307c972dcc12f4be643787b292117b2294caba2f Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 24 Sep 2024 20:17:30 +0900 Subject: [PATCH 05/49] 15 / 3sum / medium / 21m 26s --- oris8/15_3sum.js | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 oris8/15_3sum.js diff --git a/oris8/15_3sum.js b/oris8/15_3sum.js new file mode 100644 index 0000000..07ed8ac --- /dev/null +++ b/oris8/15_3sum.js @@ -0,0 +1,45 @@ +/** + * + * 정수 배열 nums에서 세 num 합이 0 이 되는 조합을 return + * 한 요소는 한 번만 사용가능하고 중복된 숫자가 있을 수 있다. 하지만 중복된 세트가 포함되서는 안된다. + * + * 3 <= nums.length <= 3000 + * -10^5 <= nums[i] <= 10^5 + * + * @param {number[]} nums + * @return {number[][]} [nums[i], nums[j], nums[k]][] + */ +const threeSum = (nums) => { + nums.sort((a, b) => a - b); + const result = []; + + for (let i = 0; i < nums.length - 2; i++) { + // sort 했으므로 index를 사용해 중복된 숫자 건너뛰기 + if (i > 0 && nums[i] === nums[i - 1]) continue; + + let left = i + 1; + let right = nums.length - 1; + + while (left < right) { + const sum = nums[i] + nums[left] + nums[right]; + if (sum === 0) { + result.push([nums[i], nums[left], nums[right]]); + + while (nums[left] === nums[left + 1]) left++; + while (nums[right] === nums[right - 1]) right--; + + left++; + right--; + } else if (sum < 0) { + left++; + } else { + right--; + } + } + } + + return result; +}; + +// Runtime: 151 ms Beats 78.51% +// Memory: 65.01MB Beats 68.03% From 072559bb0a3393a98205991ac9fd6be8fae7e963 Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 24 Sep 2024 20:32:02 +0900 Subject: [PATCH 06/49] 252 / Meeting Room / easy / 13m 18s --- oris8/252_meeting-rooms.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 oris8/252_meeting-rooms.js diff --git a/oris8/252_meeting-rooms.js b/oris8/252_meeting-rooms.js new file mode 100644 index 0000000..a60e9e9 --- /dev/null +++ b/oris8/252_meeting-rooms.js @@ -0,0 +1,28 @@ +class Solution { + /** + * 모든 회의를 충돌없이 소화 가능한지 여부 + * + * @param {Interval[]} intervals - + * class Interval { + * constructor(start, end) { + * this.start = start; + * this.end = end; + * } + * @returns {boolean} + */ + canAttendMeetings(intervals) { + // 시작 순으로 정렬한 뒤, 끝나는 시간을 기록해서 비교한다 + // if (새로운 시작시간 < 기존에 기록해둔 끝나는 시간) return false + // if (새로운 시작시간 >= 기존에 기록해둔 끝나는 시간) 끝나는 시간을 업데이트 Math.max(기존 end, 현재 end) 후 게속 진행 + intervals.sort((a, b) => a.start - b.start); + + let currentEnd = -1; + + for (const { start, end } of intervals) { + if (start < currentEnd) return false; + currentEnd = Math.max(currentEnd, end); + } + + return true; + } +} From e8d4aaabc9f1adbd2373954d643d67514ff0f1ed Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 24 Sep 2024 20:32:29 +0900 Subject: [PATCH 07/49] =?UTF-8?q?217=20/=20Contains=20Duplicate=20/=20easy?= =?UTF-8?q?=20/=202m=2054s=20(=EA=B0=9C=EC=84=A0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- oris8/217_contains-duplicate.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/oris8/217_contains-duplicate.js b/oris8/217_contains-duplicate.js index 789eb33..bb8fe33 100644 --- a/oris8/217_contains-duplicate.js +++ b/oris8/217_contains-duplicate.js @@ -15,3 +15,17 @@ const containsDuplicate = (nums) => { return nums.length !== bucket.size; }; + +// Runtime: 88 ms Beats 29.90% +// Memory: 62.83MB Beats 34.73% + +const containsDuplicate2 = (nums) => { + const bucket = new Set(); + + for (let i = 0; i < nums.length; i++) { + if (bucket.has(nums[i])) return true; + bucket.add(num); + } +}; +// Runtime: 80 ms Beats 55.24% +// Memory: 62.14MB Beats 54.23% From 46e92c501a8b332f82585e096c9c496c1bb3642d Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 24 Sep 2024 20:32:39 +0900 Subject: [PATCH 08/49] =?UTF-8?q?268=20/=20Missing=20Number=20/=20easy=20/?= =?UTF-8?q?=203m=2015s=20(=EA=B0=9C=EC=84=A0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- oris8/268_missing-number.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/oris8/268_missing-number.js b/oris8/268_missing-number.js index cfe6e74..d38140e 100644 --- a/oris8/268_missing-number.js +++ b/oris8/268_missing-number.js @@ -12,3 +12,15 @@ const missingNumber = (nums) => { if (!nums.includes(i)) return i; } }; +// Runtime: 277 ms Beats 6.21% +// Memory: 51.46MB Beats 45.81% + +// 충격적인 위치 . . 누적합으로 바꾸기 +const missingNumber2 = (nums) => { + return ( + (nums.length * (nums.length + 1)) / 2 - + nums.reduce((acc, num) => acc + num, 0) + ); +}; +// Runtime: 59 ms Beats 58.97% +// Memory: 51.29MB Beats 64.91% From d2b8ccb1047885767ac43847d6c36d6e2782b390 Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 1 Oct 2024 20:45:48 +0900 Subject: [PATCH 09/49] 242 / Valid Anagram / easy / 8m 17s --- oris8/242_valid-anagram.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 oris8/242_valid-anagram.js diff --git a/oris8/242_valid-anagram.js b/oris8/242_valid-anagram.js new file mode 100644 index 0000000..3232e96 --- /dev/null +++ b/oris8/242_valid-anagram.js @@ -0,0 +1,26 @@ +/** + * 8m 17s + * s를 애너그램해서 t를 만들 수 있는지를 판단해주는 함수 + * + * @param {string} s + * @param {string} t + * @return {boolean} + */ +const isAnagram = function (s, t) { + if (s.length !== t.length) return false; + + const map = new Map(); + + // 돌면서 각 단어의 등장 횟수를 저장 + for (const char of s) { + map[char] = (map[char] || 0) + 1; + } + + // 확인 + for (const char of t) { + if (!map[char]) return false; + map[char]--; + if (map[char] < 0) return false; + } + return true; +}; From 13eab5b62e1999e6c698a1124d5800bcba78dc87 Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 1 Oct 2024 20:46:40 +0900 Subject: [PATCH 10/49] 191 / Number of 1 Bits / easy / 5m --- oris8/191_number-of-1-bits.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 oris8/191_number-of-1-bits.js diff --git a/oris8/191_number-of-1-bits.js b/oris8/191_number-of-1-bits.js new file mode 100644 index 0000000..ab9d1a2 --- /dev/null +++ b/oris8/191_number-of-1-bits.js @@ -0,0 +1,14 @@ +/** + * 5m + * @param {number} n - 양의 정수 + * @return {number} 정수의 이진 표현에서 1의 개수 + */ +const hammingWeight = function (n) { + // 1. filter 메서드 사용 : ...연산자, filter메서드에서 각각 메모리 사용 + // return [...n.toString(2)].filter((bit) => bit === "1").length; + + // 2. 정규표현식 사용: 정규표현식 과정에서 메모리 사용 + return n.toString(2).match(/1/g).length; + + // Runtime 50 ms Beats 87.92% +}; From d0c74510d198ee1734ee0ab64f07e1f9d251271b Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 1 Oct 2024 20:47:20 +0900 Subject: [PATCH 11/49] 100 / Same Tree / easy / 21m 2s --- oris8/100_same-tree.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 oris8/100_same-tree.js diff --git a/oris8/100_same-tree.js b/oris8/100_same-tree.js new file mode 100644 index 0000000..f59225d --- /dev/null +++ b/oris8/100_same-tree.js @@ -0,0 +1,30 @@ +/** + * 21m 2s + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} p + * @param {TreeNode} q + * @return {boolean} + */ +const isSameTree = function (p, q) { + // 리프노드 [0, null, null] + if (p === null && q === null) return true; + + // 한쪽 방향이 끝났을 수 있으므로, + // null을 먼저 체크하거나 ? 이용해서 안전하게 접근 + if (p?.val !== q?.val) return false; + // if (p === null || q === null || p.val !== q.val) return false; + + // 리프노드도 아니고 서로 다른 값도 아닐 때, + // 왼쪽과 오른쪽을 재귀적으로 다시 탐색 + return isSameTree(p.left, q.left) && isSameTree(p.right, q.right); + + // Runtime 44ms Beats 92.72% + // Memory 49.23MB Beats 43.46% +}; From 39800882acda1f9be5d83f0fda41665f48132ca8 Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 1 Oct 2024 20:48:35 +0900 Subject: [PATCH 12/49] 746 / Min Cost Climbing Stairs / easy / 24m 43s --- oris8/746_min-cost-climbing-stairs.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 oris8/746_min-cost-climbing-stairs.js diff --git a/oris8/746_min-cost-climbing-stairs.js b/oris8/746_min-cost-climbing-stairs.js new file mode 100644 index 0000000..7d5b3e1 --- /dev/null +++ b/oris8/746_min-cost-climbing-stairs.js @@ -0,0 +1,24 @@ +/** + * 24m 43s + * @param {number[]} cost + * @return {number} + */ +const minCostClimbingStairs = function (cost) { + // dp[n] = min(dp[n-1] + cost[n-1], dp[n-2] + cost[n-2]) + + const { length } = cost; + const costArray = Array.from({ length: length }, () => 0); + + for (let i = 0; i < length; i++) { + if (i < 2) { + costArray[i] = cost[i]; + } else { + costArray[i] = cost[i] + Math.min(costArray[i - 1], costArray[i - 2]); + } + } + + return Math.min(costArray[length - 1], costArray[length - 2]); +}; + +// Runtime 59ms Beats 41.87% +// Memory 50.64MB Beats 34.58% From 0e0a50ce49305e8fa1cd49278f311ef284481b6b Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 1 Oct 2024 21:37:38 +0900 Subject: [PATCH 13/49] =?UTF-8?q?238=20/=20Product=20Of=20Array=20Except?= =?UTF-8?q?=20Self=20/=20medium=20/=20=E3=85=A0=E3=85=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- oris8/238_product-of-array-except-self.js | 38 +++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 oris8/238_product-of-array-except-self.js diff --git a/oris8/238_product-of-array-except-self.js b/oris8/238_product-of-array-except-self.js new file mode 100644 index 0000000..99e54de --- /dev/null +++ b/oris8/238_product-of-array-except-self.js @@ -0,0 +1,38 @@ +/** + * @param {number[]} nums + * @return {number[]} + */ +const productExceptSelf = function (nums) { + // 왼/오 나눠서 차례대로 누적곱 업데이트하는 아이디어 검색해서 구현 .... + const dp = Array.from({ length: nums.length }, (_, i) => ({ + left: nums[i - 1] ? nums[i - 1] : 1, + right: nums[i + 1] ? nums[i + 1] : 1, + })); + + for (let i = 1; i < nums.length; i++) { + dp[i].left = dp[i - 1].left * nums[i - 1]; + } + + for (let i = nums.length - 2; i >= 0; i--) { + dp[i].right = dp[i + 1].right * nums[i + 1]; + } + + return dp.map((item) => item.left * item.right); + + // Follow up 문제 공간복잡도 O(1) 만들기 + // 하나의 answer 배열을 업데이트 해주면 될 듯 + + const result = Array(nums.length).fill(1); + + let currentLeft = 1; + for (let i = 0; i < nums.length; i++) { + result[i] = currentLeft; + currentLeft *= nums[i]; + } + let currentRight = 1; + for (let i = nums.length - 1; i >= 0; i--) { + result[i] *= currentRight; + currentRight *= nums[i]; + } + return result; +}; From 94e8f36591bb6386539c8f17cdb0bc0357bd2594 Mon Sep 17 00:00:00 2001 From: eprnf Date: Wed, 9 Oct 2024 10:26:00 +0900 Subject: [PATCH 14/49] 49 / Group Anagrams / medium / 5m 24s --- oris8/49_group-anagram.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 oris8/49_group-anagram.js diff --git a/oris8/49_group-anagram.js b/oris8/49_group-anagram.js new file mode 100644 index 0000000..24e08c2 --- /dev/null +++ b/oris8/49_group-anagram.js @@ -0,0 +1,21 @@ +/** + * @param {string[]} strs + * @return {string[][]} + */ +function groupAnagrams(strs) { + const map = new Map(); + + strs.forEach((str) => { + const sorted = str.split("").sort().join(""); + + if (!map.has(sorted)) { + map.set(sorted, []); + } + map.get(sorted).push(str); + }); + + return Array.from(map.values()); + + // Runtime 95ms 96.95% + // Memory 63.61MB 35.50% +} From 9d8304a9fca4863d20cad2ca2ea30d0dff275cb4 Mon Sep 17 00:00:00 2001 From: eprnf Date: Wed, 9 Oct 2024 10:36:10 +0900 Subject: [PATCH 15/49] 190 / Reverse Bits / easy / 12m 14s --- oris8/190_reverse-bits.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 oris8/190_reverse-bits.js diff --git a/oris8/190_reverse-bits.js b/oris8/190_reverse-bits.js new file mode 100644 index 0000000..4272c6a --- /dev/null +++ b/oris8/190_reverse-bits.js @@ -0,0 +1,16 @@ +/** + * @param {number} n - a positive integer + * @return {number} - a positive integer + */ +var reverseBits = function (n) { + const reversedStr = n + .toString(2) + .padStart(32, "0") // 32 bits + .split("") + .reverse() + .join(""); + return parseInt(reversedStr, 2); + + // Runtime 59ms 56.54% + // Memory 50.63MB 82.99% +}; From bd642494e67b4069ee99fdf06353fb5a13052ef0 Mon Sep 17 00:00:00 2001 From: eprnf Date: Wed, 9 Oct 2024 10:37:57 +0900 Subject: [PATCH 16/49] 125 / Valid Palindrome / easy / 4m 3s --- oris8/125_valid-palindrome.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 oris8/125_valid-palindrome.js diff --git a/oris8/125_valid-palindrome.js b/oris8/125_valid-palindrome.js new file mode 100644 index 0000000..89a0add --- /dev/null +++ b/oris8/125_valid-palindrome.js @@ -0,0 +1,17 @@ +/** + * @param {string} s + * @return {boolean} + */ +var isPalindrome = function (s) { + s = s.toLowerCase().replace(/[^a-z0-9]/g, ""); + + for (let i = 0; i < Math.floor(s.length / 2); i++) { + if (s.charAt(i) !== s.charAt(s.length - i - 1)) { + return false; + } + } + return true; + + // Runtime 48ms 98.15% + // Memory 50.62MB Beats 97.72% +}; From 3cdb5c4590f8ad4374c8973a4e8e4332568a9556 Mon Sep 17 00:00:00 2001 From: eprnf Date: Wed, 9 Oct 2024 11:02:51 +0900 Subject: [PATCH 17/49] 206 / Reverse Linked List / easy / 10m 47s --- oris8/206_reverse-linked-list.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 oris8/206_reverse-linked-list.js diff --git a/oris8/206_reverse-linked-list.js b/oris8/206_reverse-linked-list.js new file mode 100644 index 0000000..553b527 --- /dev/null +++ b/oris8/206_reverse-linked-list.js @@ -0,0 +1,23 @@ +/** + * 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} + */ +var reverseList = function (head) { + if (head === null || head.next === null) { + return head; + } + const newHead = reverseList(head.next); + head.next.next = head; + head.next = null; + return newHead; + + // Runtime 57ms 70.71% + // Memory 52.22MB 18.09% +}; From ebe8b2c058766abb2505fc7405e7de7e6fd4ff30 Mon Sep 17 00:00:00 2001 From: eprnf Date: Wed, 9 Oct 2024 11:06:05 +0900 Subject: [PATCH 18/49] 322 / Coin Change / medium / 21m 7s --- oris8/322_coin-change.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 oris8/322_coin-change.js diff --git a/oris8/322_coin-change.js b/oris8/322_coin-change.js new file mode 100644 index 0000000..960de55 --- /dev/null +++ b/oris8/322_coin-change.js @@ -0,0 +1,26 @@ +/** + * @param {number[]} coins + * @param {number} amount + * @return {number} + */ +var coinChange = function (coins, amount) { + // 각 금액마다 최소 동전 수를 업데이트 + // dp[i] = Math.min(dp[i], dp[i - coin] + 1) + + const dp = Array(amount + 1).fill(Infinity); + dp[0] = 0; + + // 각 금액에 대해 동전 수 계산 + for (let i = 1; i <= amount; i++) { + for (let coin of coins) { + if (i - coin >= 0) { + dp[i] = Math.min(dp[i], dp[i - coin] + 1); + } + } + } + + return dp[amount] === Infinity ? -1 : dp[amount]; + + // Runtime 89ms 79.42% + // Memory 55.13MB 53.20% +}; From 0203ee7856b55bffc824bee78eb347cbb7c27eb2 Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 15 Oct 2024 21:20:05 +0900 Subject: [PATCH 19/49] 1 / Two Sum / easy / 8m 21s --- oris8/1_2sum.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 oris8/1_2sum.js diff --git a/oris8/1_2sum.js b/oris8/1_2sum.js new file mode 100644 index 0000000..7e33e47 --- /dev/null +++ b/oris8/1_2sum.js @@ -0,0 +1,26 @@ +/** + * 8m 21s + * + * @param {number[]} nums + * @param {number} target + * @return {number[]} + */ +const twoSum = function (nums, target) { + const sortedNums = nums + .map((value, index) => ({ value, index })) + .sort((a, b) => a.value - b.value); + + let left = 0; + let right = sortedNums.length - 1; + + while (left < right) { + const sum = sortedNums[left].value + sortedNums[right].value; + if (sum === target) { + return [sortedNums[left].index, sortedNums[right].index]; + } + + sum > target ? right-- : left++; + } + + return []; +}; From 3d6bf362b101e94c5e1c5d90c9aaa67030df3443 Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 15 Oct 2024 21:21:02 +0900 Subject: [PATCH 20/49] 104 / Maximun Depth of Binary Tree / easy / 3m 20 --- oris8/104_maximum-depth-of-binary-tree.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 oris8/104_maximum-depth-of-binary-tree.js diff --git a/oris8/104_maximum-depth-of-binary-tree.js b/oris8/104_maximum-depth-of-binary-tree.js new file mode 100644 index 0000000..85cf2c5 --- /dev/null +++ b/oris8/104_maximum-depth-of-binary-tree.js @@ -0,0 +1,22 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * 3m 20s + * + * @param {TreeNode} root + * @return {number} + */ +const maxDepth = function (root) { + if (root === null) return 0; // 재귀 종료 조건 + + const leftDepth = maxDepth(root.left); + const rightDepth = maxDepth(root.right); + + return Math.max(leftDepth, rightDepth) + 1; +}; From ad1a985053e52f506cdc8fd6741a81cc4580ee38 Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 15 Oct 2024 21:21:35 +0900 Subject: [PATCH 21/49] 141 / Linked List Cycle / easy / 3m 12s --- oris8/141_linked-list-cycle.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 oris8/141_linked-list-cycle.js diff --git a/oris8/141_linked-list-cycle.js b/oris8/141_linked-list-cycle.js new file mode 100644 index 0000000..28892ab --- /dev/null +++ b/oris8/141_linked-list-cycle.js @@ -0,0 +1,25 @@ +/** + * 3m 12s + * + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ + +/** + * @param {ListNode} head + * @return {boolean} + */ +var hasCycle = function (head) { + const map = new Map(); + + while (head) { + if (map.has(head)) return true; + map.set(head, true); + head = head.next; + } + + return false; +}; From dbae9bda90a55ab28f014f7149b5de74a3980720 Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 15 Oct 2024 21:22:29 +0900 Subject: [PATCH 22/49] 202 / Happy Number / Easy / 7m 10s --- oris8/202_happy-number.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 oris8/202_happy-number.js diff --git a/oris8/202_happy-number.js b/oris8/202_happy-number.js new file mode 100644 index 0000000..20fca00 --- /dev/null +++ b/oris8/202_happy-number.js @@ -0,0 +1,15 @@ +/** + * @param {number} n + * @return {boolean} + */ +const isHappy = function (n) { + // 무한루프 가능성 + const map = new Map(); + if (n === 1) return true; + if (map.has(n)) return false; + + map.set(n, true); + + n = [...`${n}`].reduce((acc, digit) => acc + Math.pow(+digit, 2), 0); + return isHappy(n); +}; From fc17d7b83e4a858054d3503c75f287e6af9b052a Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 15 Oct 2024 21:41:32 +0900 Subject: [PATCH 23/49] 20 / Valid Parentheses / easy / 10m 48s --- oris8/20_valid-parentheses.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 oris8/20_valid-parentheses.js diff --git a/oris8/20_valid-parentheses.js b/oris8/20_valid-parentheses.js new file mode 100644 index 0000000..d901fce --- /dev/null +++ b/oris8/20_valid-parentheses.js @@ -0,0 +1,26 @@ +/** + * @param {string} s + * @return {boolean} + */ +var isValid = function (s) { + // 여는 괄호는 스택에 추가하고, 닫는 괄호는 스택에서 제거 + const bracketPairs = { + ")": "(", + "}": "{", + "]": "[", + }; + + const stack = []; + + for (const char of s) { + if (char === "(" || char === "{" || char === "[") { + stack.push(char); + } else if (bracketPairs[char]) { + if (stack.length === 0 || stack.pop() !== bracketPairs[char]) { + return false; + } + } + } + + return stack.length === 0; +}; From 020b8cb447222c325feba6517e10f768bc1864d8 Mon Sep 17 00:00:00 2001 From: eprnf Date: Wed, 23 Oct 2024 11:03:33 +0900 Subject: [PATCH 24/49] 338 / Counting Bits / easy --- oris8/338_counting-bits.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 oris8/338_counting-bits.js diff --git a/oris8/338_counting-bits.js b/oris8/338_counting-bits.js new file mode 100644 index 0000000..241df27 --- /dev/null +++ b/oris8/338_counting-bits.js @@ -0,0 +1,13 @@ +/** + * @param {number} n + * @return {number[]} + */ +var countBits = function (n) { + const ans = new Array(n + 1).fill(0); + + for (let i = 1; i <= n; i++) { + ans[i] = ans[i >> 1] + (i & 1); + } + + return ans; +}; From 76acecbfaffa82abb2521ff936ee5868ec872c05 Mon Sep 17 00:00:00 2001 From: eprnf Date: Wed, 23 Oct 2024 11:04:47 +0900 Subject: [PATCH 25/49] 70 / Climbing Stairs / easy / 8m 19s --- oris8/70_climbing-stairs.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 oris8/70_climbing-stairs.js diff --git a/oris8/70_climbing-stairs.js b/oris8/70_climbing-stairs.js new file mode 100644 index 0000000..a2d8b18 --- /dev/null +++ b/oris8/70_climbing-stairs.js @@ -0,0 +1,18 @@ +/** + * @param {number} n + * @return {number} + */ +var climbStairs = function (n) { + if (n === 1) return 1; + + let first = 1, + second = 2; + + for (let i = 3; i <= n; i++) { + let third = first + second; + first = second; + second = third; + } + + return second; +}; From baeafc5f1bd7cce2765baa5e5980b5f130b60123 Mon Sep 17 00:00:00 2001 From: eprnf Date: Wed, 23 Oct 2024 11:05:56 +0900 Subject: [PATCH 26/49] 21 / Merge Two Sorted Lists / easy / 13m --- oris8/21_merge-two-sorted-lists.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 oris8/21_merge-two-sorted-lists.js diff --git a/oris8/21_merge-two-sorted-lists.js b/oris8/21_merge-two-sorted-lists.js new file mode 100644 index 0000000..df068f5 --- /dev/null +++ b/oris8/21_merge-two-sorted-lists.js @@ -0,0 +1,24 @@ +/** + * Definition for singly-linked list. + * function ListNode(val, next) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + */ +/** + * @param {ListNode} list1 + * @param {ListNode} list2 + * @return {ListNode} + */ +var mergeTwoLists = function (list1, list2) { + if (list1 === null) return list2; + if (list2 === null) return list1; + + if (list1.val <= list2.val) { + list1.next = mergeTwoLists(list1.next, list2); + return list1; + } else { + list2.next = mergeTwoLists(list1, list2.next); + return list2; + } +}; From 05a9eb4e864f92662854bb83c26f59c0e896b8d5 Mon Sep 17 00:00:00 2001 From: eprnf Date: Wed, 23 Oct 2024 11:06:57 +0900 Subject: [PATCH 27/49] 48 / Rotate Image / medium / 14m 21s --- oris8/48_rotate-image.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 oris8/48_rotate-image.js diff --git a/oris8/48_rotate-image.js b/oris8/48_rotate-image.js new file mode 100644 index 0000000..4f800c0 --- /dev/null +++ b/oris8/48_rotate-image.js @@ -0,0 +1,19 @@ +/** + * @param {number[][]} matrix + * @return {void} Do not return anything, modify matrix in-place instead. + */ +var rotate = function (matrix) { + const { length } = matrix; + + for (let i = 0; i < length; i++) { + for (let j = i; j < length; j++) { + let temp = matrix[i][j]; + matrix[i][j] = matrix[j][i]; + matrix[j][i] = temp; + } + } + + for (let i = 0; i < length; i++) { + matrix[i].reverse(); + } +}; From c514e4dec2fc8fc57530c6d402fc897afee5a06f Mon Sep 17 00:00:00 2001 From: eprnf Date: Wed, 23 Oct 2024 11:09:05 +0900 Subject: [PATCH 28/49] 1046 / Last Stone Weight / easy / 18m 5s --- oris8/1046_last-stone-weight.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 oris8/1046_last-stone-weight.js diff --git a/oris8/1046_last-stone-weight.js b/oris8/1046_last-stone-weight.js new file mode 100644 index 0000000..78ae155 --- /dev/null +++ b/oris8/1046_last-stone-weight.js @@ -0,0 +1,18 @@ +/** + * @param {number[]} stones + * @return {number} + */ +var lastStoneWeight = function (stones) { + while (stones.length > 1) { + stones.sort((a, b) => b - a); + + const stone1 = stones.shift(); + const stone2 = stones.shift(); + + if (stone1 !== stone2) { + stones.push(stone1 - stone2); + } + } + + return stones.length === 1 ? stones[0] : 0; +}; From a226562e30ed81e9103047a4f5fb640c8681612a Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 5 Nov 2024 19:21:14 +0900 Subject: [PATCH 29/49] 198 / House Robber / medium / 10m 16s --- oris8/198_house-robber.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 oris8/198_house-robber.js diff --git a/oris8/198_house-robber.js b/oris8/198_house-robber.js new file mode 100644 index 0000000..69874bb --- /dev/null +++ b/oris8/198_house-robber.js @@ -0,0 +1,22 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const rob = function (nums) { + // 인접한 두 집을 털지 않으면서 최대로 많이 훔칠 수 있는 금액을 찾기 + // T(n) = max(n + T(n−2) , T(n−1)) + + const cache = Array.from({ length: nums.length }, () => 0); + + cache[0] = nums[0]; + + for (let i = 1; i < nums.length; i++) { + if (i === 1) { + cache[1] = Math.max(nums[0], nums[1]); + } else { + cache[i] = Math.max(cache[i - 1], cache[i - 2] + nums[i]); + } + } + + return cache.pop(); +}; From 46cf7c4d6215e2fa46b91c0ad681f54a2412befe Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 5 Nov 2024 19:33:56 +0900 Subject: [PATCH 30/49] 66 / Plus One / easy / 10m 54s --- oris8/66_plus-one.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 oris8/66_plus-one.js diff --git a/oris8/66_plus-one.js b/oris8/66_plus-one.js new file mode 100644 index 0000000..6acc8ba --- /dev/null +++ b/oris8/66_plus-one.js @@ -0,0 +1,20 @@ +/** + * @param {number[]} digits + * @return {number[]} + */ +const plusOne = function (digits) { + let currentIndex = digits.length - 1; + let last = digits[currentIndex]; + + while (last === 9) { + digits[currentIndex] = 0; + if (currentIndex === 0) return [1, ...digits]; + + currentIndex -= 1; + last = digits[currentIndex]; + } + + digits[currentIndex] += 1; + + return digits; +}; From 6e0bf61a961bbe45acf452f942315bb9ccc498cf Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 5 Nov 2024 19:49:35 +0900 Subject: [PATCH 31/49] 704 / Binary Search / easy / 8m 12s --- oris8/704_binary-search.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 oris8/704_binary-search.js diff --git a/oris8/704_binary-search.js b/oris8/704_binary-search.js new file mode 100644 index 0000000..c7eb306 --- /dev/null +++ b/oris8/704_binary-search.js @@ -0,0 +1,21 @@ +/** + * @param {number[]} nums + * @param {number} target + * @return {number} + */ +const search = function (nums, target) { + const binarySearch = function (left, right) { + if (left > right) { + return -1; + } + + const pivotIndex = Math.floor((left + right) / 2); + const pivot = nums[pivotIndex]; + + if (pivot === target) return pivotIndex; + if (pivot < target) return binarySearch(pivotIndex + 1, right); + return binarySearch(left, pivotIndex - 1); + }; + + return binarySearch(0, nums.length - 1); +}; From 4187edfdc7ef9eeb75027928ebe6dc514df7a4f7 Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 5 Nov 2024 20:10:46 +0900 Subject: [PATCH 32/49] 703 / Kth Largest Element in a Stream / Easy / 12m 10s --- oris8/703_kth-largest-element-in-a-stream.js | 24 ++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 oris8/703_kth-largest-element-in-a-stream.js diff --git a/oris8/703_kth-largest-element-in-a-stream.js b/oris8/703_kth-largest-element-in-a-stream.js new file mode 100644 index 0000000..50cd408 --- /dev/null +++ b/oris8/703_kth-largest-element-in-a-stream.js @@ -0,0 +1,24 @@ +/** + * @param {number} k + * @param {number[]} nums + */ +const KthLargest = function (k, nums) { + const minHeap = []; + + const add = (val) => { + minHeap.push(val); + minHeap.sort((a, b) => a - b); + + if (minHeap.length > k) { + minHeap.shift(); + } + + return minHeap[0]; + }; + + nums.forEach((num) => add(num)); + + return { + add, + }; +}; From 5a2f27da2012a9b07b36a255dc61d12f99d4fac8 Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 5 Nov 2024 20:14:20 +0900 Subject: [PATCH 33/49] 271 / String Encode and Decode / medium / ... --- oris8/271_string-encode-and-decode.js | 36 +++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 oris8/271_string-encode-and-decode.js diff --git a/oris8/271_string-encode-and-decode.js b/oris8/271_string-encode-and-decode.js new file mode 100644 index 0000000..2e100b2 --- /dev/null +++ b/oris8/271_string-encode-and-decode.js @@ -0,0 +1,36 @@ +// 문자열 길이 + # 을 이용해 encode +// while문을 돌면서 decode +class Solution { + /** + * @param {string[]} strs + * @returns {string} + */ + encode(strs) { + let res = ""; + for (let s of strs) { + res += s.length + "#" + s; + } + return res; + } + + /** + * @param {string} str + * @returns {string[]} + */ + decode(str) { + let res = []; + let i = 0; + while (i < str.length) { + let j = i; + while (str[j] !== "#") { + j++; + } + let length = parseInt(str.substring(i, j)); + i = j + 1; + j = i + length; + res.push(str.substring(i, j)); + i = j; + } + return res; + } +} From 6baade0a25815671b0ea0c61ede68fb5bd0fc5fe Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 12 Nov 2024 20:12:01 +0900 Subject: [PATCH 34/49] 136 / Single Number / easy / 3m 5s --- oris8/136_single-number.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 oris8/136_single-number.js diff --git a/oris8/136_single-number.js b/oris8/136_single-number.js new file mode 100644 index 0000000..7756514 --- /dev/null +++ b/oris8/136_single-number.js @@ -0,0 +1,14 @@ +/** + * 요구사항 TO(n) O(1) + * 1번만 나타나는 요소 찾기 + * @param {number[]} nums + * @return {number} + */ +const singleNumber = function (nums) { + nums.sort((a, b) => a - b); + for (let i = 0; i < nums.length; i += 2) { + if (i === nums.length - 1 || nums[i] !== nums[i + 1]) return nums[i]; + } +}; + +// 다른 풀이 xor 연산 이용해서 풀기 (중복된 같은 없어지는 특징) From a959c5d92f95ce2f2122d11175a871f9e1872b17 Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 12 Nov 2024 20:41:11 +0900 Subject: [PATCH 35/49] 973 / K Closest Points to Origin / Medium / 7m 40s --- oris8/973_k-closest-points-to-origin.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 oris8/973_k-closest-points-to-origin.js diff --git a/oris8/973_k-closest-points-to-origin.js b/oris8/973_k-closest-points-to-origin.js new file mode 100644 index 0000000..e2d967a --- /dev/null +++ b/oris8/973_k-closest-points-to-origin.js @@ -0,0 +1,13 @@ +/** + * @param {number[][]} points + * @param {number} k + * @return {number[][]} + */ +const kClosest = function (points, k) { + return points + .sort( + ([x1, y1], [x2, y2]) => + Math.sqrt(x1 ** 2 + y1 ** 2) - Math.sqrt(x2 ** 2 + y2 ** 2) + ) + .slice(0, k); +}; From 3491cea891da5096955e99550b8687a281ae1cc8 Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 12 Nov 2024 20:44:33 +0900 Subject: [PATCH 36/49] 110 / Balanced Binary Tree / easy / 12m 10s --- oris8/110_balanced-binary-tree.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 oris8/110_balanced-binary-tree.js diff --git a/oris8/110_balanced-binary-tree.js b/oris8/110_balanced-binary-tree.js new file mode 100644 index 0000000..4be385d --- /dev/null +++ b/oris8/110_balanced-binary-tree.js @@ -0,0 +1,28 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @return {boolean} + */ +var isBalanced = function (root) { + const heightDiff = function (node) { + if (!node) return 0; + const leftHeight = heightDiff(node.left); + const rightHeight = heightDiff(node.right); + if ( + leftHeight === -1 || + rightHeight === -1 || + Math.abs(leftHeight - rightHeight) > 1 + ) { + return -1; + } + return Math.max(leftHeight, rightHeight) + 1; + }; + return heightDiff(root) !== -1; +}; From 672bf833ab14cbb1ba542b3538e07a7bfc2ef185 Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 12 Nov 2024 20:56:18 +0900 Subject: [PATCH 37/49] 155 / Min Stack / midium / 10m 18s --- oris8/155_min-stack.js | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 oris8/155_min-stack.js diff --git a/oris8/155_min-stack.js b/oris8/155_min-stack.js new file mode 100644 index 0000000..3d85860 --- /dev/null +++ b/oris8/155_min-stack.js @@ -0,0 +1,35 @@ +class MinStack { + constructor() { + this.stack = []; + this.min = Infinity; + } + + push(val) { + this.min = Math.min(this.min, val); + this.stack.push(val); + } + + pop() { + const top = this.stack.pop(); + if (top === this.min) { + this.min = Math.min(...this.stack); + } + } + + top() { + return this.stack.at(-1); + } + + getMin() { + return this.min; + } +} + +/** + * Your MinStack object will be instantiated and called as such: + * var obj = new MinStack() + * obj.push(val) + * obj.pop() + * var param_3 = obj.top() + * var param_4 = obj.getMin() + */ From 42d5b15de3d8b312fda0177e027894f0e26924ff Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 12 Nov 2024 21:31:46 +0900 Subject: [PATCH 38/49] 54 / Spiral Matrix / medium / 28m 20s --- oris8/54_spiral-matrix.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 oris8/54_spiral-matrix.js diff --git a/oris8/54_spiral-matrix.js b/oris8/54_spiral-matrix.js new file mode 100644 index 0000000..89ec8d7 --- /dev/null +++ b/oris8/54_spiral-matrix.js @@ -0,0 +1,18 @@ +/** + * @param {number[][]} matrix + * @return {number[]} + */ +var spiralOrder = function (matrix) { + let result = []; + while (matrix.length > 0) { + const currentLine = matrix.shift(); + result = [...result, ...currentLine]; + if (!matrix[0]) break; + matrix = transposeMatrix(matrix).reverse(); + } + return result; +}; + +function transposeMatrix(matrix) { + return matrix[0].map((_, colIndex) => matrix.map((row) => row[colIndex])); +} From e4018011102d1d5bdebfb7806ccfcc2c054a35f4 Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 19 Nov 2024 19:26:52 +0900 Subject: [PATCH 39/49] 128 / Longest Consecutive Sequence / medium / 6m 27s --- oris8/128_longest-consecutive-sequence.js | 35 +++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 oris8/128_longest-consecutive-sequence.js diff --git a/oris8/128_longest-consecutive-sequence.js b/oris8/128_longest-consecutive-sequence.js new file mode 100644 index 0000000..c7e1fe4 --- /dev/null +++ b/oris8/128_longest-consecutive-sequence.js @@ -0,0 +1,35 @@ +/** + * + * 128. Longest Consecutive Sequence + * Medium + * Topics + * Companies + * Given an unsorted array of integers nums, return the length of the longest consecutive elements sequence. + * + * You must write an algorithm that runs in O(n) time. + * @param {number[]} nums + * @return {number} + */ +var longestConsecutive = function (nums) { + // 중복되는 요소 허용, 빈 배열 허용 + if (nums.length === 0) return 0; + + const set = new Set(nums); + const sortedSet = Array.from(set).sort((a, b) => a - b); + + let maxSequenceLength = 1; + let currentSequence = [sortedSet[0]]; + + for (let i = 1; i < sortedSet.length; i++) { + const last = currentSequence.pop(); + if (last + 1 === sortedSet[i]) { + currentSequence.push(last); + currentSequence.push(sortedSet[i]); + } else { + currentSequence = [sortedSet[i]]; + } + maxSequenceLength = Math.max(maxSequenceLength, currentSequence.length); + } + + return maxSequenceLength; +}; From 2ff832675cb920acef3f322d25db274de4b82120 Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 19 Nov 2024 19:59:33 +0900 Subject: [PATCH 40/49] 208 / Implement Trie (Prefix Tree) / medium / 13m 30s --- oris8/208_implement-trie-prefix-tree.js | 88 +++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 oris8/208_implement-trie-prefix-tree.js diff --git a/oris8/208_implement-trie-prefix-tree.js b/oris8/208_implement-trie-prefix-tree.js new file mode 100644 index 0000000..afe03eb --- /dev/null +++ b/oris8/208_implement-trie-prefix-tree.js @@ -0,0 +1,88 @@ +/** + * 208. Implement Trie (Prefix Tree) +Medium +Topics +Companies +A trie (pronounced as "try") or prefix tree is a tree data structure used to efficiently store and retrieve keys in a dataset of strings. There are various applications of this data structure, such as autocomplete and spellchecker. + +Implement the Trie class: + +Trie() Initializes the trie object. +void insert(String word) Inserts the string word into the trie. +boolean search(String word) Returns true if the string word is in the trie (i.e., was inserted before), and false otherwise. +boolean startsWith(String prefix) Returns true if there is a previously inserted string word that has the prefix prefix, and false otherwise. + +1 <= word.length, prefix.length <= 2000 +word and prefix consist only of lowercase English letters. +At most 3 * 104 calls in total will be made to insert, search, and startsWith. + */ + +// var Trie = function() { +// node +// }; + +class TrieNode { + constructor() { + this.children = {}; + this.words = new Set(); + } +} + +class Trie { + constructor() { + this.root = new TrieNode(); + } +} + +/** + * @param {string} word + * @return {void} + */ +Trie.prototype.insert = function (word) { + let node = this.root; + for (const char of word) { + if (!node.children[char]) { + node.children[char] = new TrieNode(); + } + node = node.children[char]; + } + node.words.add(word); +}; + +/** + * @param {string} word + * @return {boolean} + */ +Trie.prototype.search = function (word) { + let node = this.root; + for (const char of word) { + if (!node.children[char]) { + return false; + } + node = node.children[char]; + } + return !!node.words.has(word); +}; + +/** + * @param {string} prefix + * @return {boolean} + */ +Trie.prototype.startsWith = function (prefix) { + let node = this.root; + for (const char of prefix) { + if (!node.children[char]) { + return false; + } + node = node.children[char]; + } + return true; +}; + +/** + * Your Trie object will be instantiated and called as such: + * var obj = new Trie() + * obj.insert(word) + * var param_2 = obj.search(word) + * var param_3 = obj.startsWith(prefix) + */ From 2e0cf6082f49acf7151a3921b112e965a3b3bc17 Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 19 Nov 2024 20:02:54 +0900 Subject: [PATCH 41/49] =?UTF-8?q?208=20/=20Implement=20Trie=20(Prefix=20Tr?= =?UTF-8?q?ee)=20/=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 중복되는 코드 분리 - 시간복잡도 11.88% -> 27.22% --- oris8/208_implement-trie-prefix-tree.js | 29 +++++++++++-------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/oris8/208_implement-trie-prefix-tree.js b/oris8/208_implement-trie-prefix-tree.js index afe03eb..69dbf2f 100644 --- a/oris8/208_implement-trie-prefix-tree.js +++ b/oris8/208_implement-trie-prefix-tree.js @@ -32,6 +32,15 @@ class Trie { constructor() { this.root = new TrieNode(); } + + traverse(word) { + let node = this.root; + for (let char of word) { + node = node.children[char]; + if (!node) return null; + } + return node; + } } /** @@ -54,14 +63,8 @@ Trie.prototype.insert = function (word) { * @return {boolean} */ Trie.prototype.search = function (word) { - let node = this.root; - for (const char of word) { - if (!node.children[char]) { - return false; - } - node = node.children[char]; - } - return !!node.words.has(word); + let node = this.traverse(word); + return !!node && node.words.has(word); }; /** @@ -69,14 +72,8 @@ Trie.prototype.search = function (word) { * @return {boolean} */ Trie.prototype.startsWith = function (prefix) { - let node = this.root; - for (const char of prefix) { - if (!node.children[char]) { - return false; - } - node = node.children[char]; - } - return true; + let node = this.traverse(prefix); + return !!node; }; /** From 3d7caf71de09ff09636810a6db0f06050499d3f2 Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 19 Nov 2024 20:15:04 +0900 Subject: [PATCH 42/49] 226 / Invert Binary Tree / easy / 6m 13s --- oris8/226_invert-binary-tree.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 oris8/226_invert-binary-tree.js diff --git a/oris8/226_invert-binary-tree.js b/oris8/226_invert-binary-tree.js new file mode 100644 index 0000000..dc122b1 --- /dev/null +++ b/oris8/226_invert-binary-tree.js @@ -0,0 +1,21 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @return {TreeNode} + */ +var invertTree = function (root) { + if (root) { + [root.right, root.left] = [invertTree(root.left), invertTree(root.right)]; + } + // if (!root) return null; + // [root.left, root.right] = [invertTree(root.right), invertTree(root.left)]; + + return root; +}; From 189df48372d399d8c7c3a7cde17dcc51b1b1fd40 Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 19 Nov 2024 20:32:44 +0900 Subject: [PATCH 43/49] 543 / Diameter of Binary Tree / easy / 13m 46s --- oris8/543_diameter-of-binary-tree.js | 44 ++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 oris8/543_diameter-of-binary-tree.js diff --git a/oris8/543_diameter-of-binary-tree.js b/oris8/543_diameter-of-binary-tree.js new file mode 100644 index 0000000..74e03c9 --- /dev/null +++ b/oris8/543_diameter-of-binary-tree.js @@ -0,0 +1,44 @@ +/** + * + * 543. Diameter of Binary Tree +Easy +Topics +Companies +Given the root of a binary tree, return the length of the diameter of the tree. + +The diameter of a binary tree is the length of the longest path between any two nodes in a tree. This path may or may not pass through the root. + +The length of a path between two nodes is represented by the number of edges between them. + +The number of nodes in the tree is in the range [1, 104]. +-100 <= Node.val <= 100 + + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @return {number} + */ +var diameterOfBinaryTree = function (root) { + let maxDiameter = 0; + const getBinaryTreeHeight = (node) => { + if (!node) return 0; + + // 현재 노드부터 높이를 재귀적으로 계산 + const right = getBinaryTreeHeight(node.right); + const left = getBinaryTreeHeight(node.left); + + maxDiameter = Math.max(maxDiameter, right + left); + + // 현재 노드를 포함하기 위해 + 1 + return Math.max(right, left) + 1; + }; + + getBinaryTreeHeight(root); + return maxDiameter; +}; From 79ad803648378482e6d7c5a638475b499df5fed4 Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 19 Nov 2024 20:33:08 +0900 Subject: [PATCH 44/49] 371 / Sum of Two Integers / medium / - --- oris8/371_sum-of-two-integers.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 oris8/371_sum-of-two-integers.js diff --git a/oris8/371_sum-of-two-integers.js b/oris8/371_sum-of-two-integers.js new file mode 100644 index 0000000..6c24788 --- /dev/null +++ b/oris8/371_sum-of-two-integers.js @@ -0,0 +1,27 @@ +/** + * 371. Sum of Two Integers + * Medium + * + * Given two integers a and b, return the sum of the two integers without using the operators + and -. + * + * -1000 <= a, b <= 1000 + * + * @param {number} a + * @param {number} b + * @return {number} + */ +var getSum = function (a, b) { + // 비트 연산 사용 + /** + * + * XOR :각 비트를 비교하여, 두 비트가 서로 다르면 1을 반환하고, 같으면 0을 반환 + * === carry(올림)를 무시한 덧셈과 동일한 결과 + * + * AND :두 비트가 모두 1인 경우 + * + * 자리올림은 두 비트가 모두 1일때 발생하므로 AND 연산을 통해서 이를 확인하고, 두 비트가 모두 1일 경우 자리올림 수행 (<<) + * + */ + + return b === 0 ? a : getSum(a ^ b, (a & b) << 1); +}; From f91da6857a72a4e021baea2df752f6df11367aa2 Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 26 Nov 2024 21:19:38 +0900 Subject: [PATCH 45/49] 102 / Binary Tree Level Order Traversal / Medium / 12m 8s --- .../102_binary-tree-level-order-traversal.js | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 oris8/102_binary-tree-level-order-traversal.js diff --git a/oris8/102_binary-tree-level-order-traversal.js b/oris8/102_binary-tree-level-order-traversal.js new file mode 100644 index 0000000..ef1f308 --- /dev/null +++ b/oris8/102_binary-tree-level-order-traversal.js @@ -0,0 +1,66 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * + * 102 / Binary Tree Level Order Traversal / Medium / 12m 8s + */ +/** + * @param {TreeNode} root + * @return {number[][]} + */ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @return {number[][]} + */ +var levelOrder = function (root) { + if (!root) return []; + + const result = []; + const queue = [root]; + + while (queue.length > 0) { + const levelSize = queue.length; + const currentLevel = []; + + for (let i = 0; i < levelSize; i++) { + const node = queue.shift(); + currentLevel.push(node.val); + + if (node.left) queue.push(node.left); + if (node.right) queue.push(node.right); + } + + result.push(currentLevel); + } + + return result; +}; + +// var levelOrder = function(root) { +// const result = []; + +// const traverse = (node, level) => { +// if (!node) return; +// if (result.length === level) { +// result.push([]); // 새로운 레벨 생성 +// } +// result[level].push(node.val); // 현재 레벨에 값 추가 +// traverse(node.left, level + 1); // 왼쪽 자식 탐색 +// traverse(node.right, level + 1); // 오른쪽 자식 탐색 +// }; + +// traverse(root, 0); +// return result; +// }; From 809d4f386e4b00610abb02c08b9a126a41eccffa Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 26 Nov 2024 21:22:13 +0900 Subject: [PATCH 46/49] 572 / Subtree of Another Tree / Easy / 23m 12s --- oris8/572_subtree-of-another-tree.js | 30 ++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 oris8/572_subtree-of-another-tree.js diff --git a/oris8/572_subtree-of-another-tree.js b/oris8/572_subtree-of-another-tree.js new file mode 100644 index 0000000..17ca2b7 --- /dev/null +++ b/oris8/572_subtree-of-another-tree.js @@ -0,0 +1,30 @@ +/** + * + * 572 / Subtree of Another Tree / Easy / 23m 12s + * + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @param {TreeNode} subRoot + * @return {boolean} + */ +var isSubtree = function (root, subRoot) { + if (!root) return false; + + if (isSameTree(root, subRoot)) return true; + + return isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot); +}; + +var isSameTree = function (t1, t2) { + if (!t1 && !t2) return true; + if (!t1 || !t2 || t1.val !== t2.val) return false; + + return isSameTree(t1.left, t2.left) && isSameTree(t1.right, t2.right); +}; From d9fe54e6f71ec1d8fb9983a451a58b34c82cc871 Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 26 Nov 2024 21:22:30 +0900 Subject: [PATCH 47/49] 213 / House Robber II / Medium / 13m 27s --- oris8/213_house-robber-ii.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 oris8/213_house-robber-ii.js diff --git a/oris8/213_house-robber-ii.js b/oris8/213_house-robber-ii.js new file mode 100644 index 0000000..ccc35ab --- /dev/null +++ b/oris8/213_house-robber-ii.js @@ -0,0 +1,19 @@ +/** + * 213 / House Robber II / Medium / 13m 27s +/** + * @param {number[]} nums + * @return {number} + */ +var rob = function (nums) { + // T(n) = Math.max(T(n-1), T(n-2) + n) + if (nums.length <= 2) return Math.max(nums[0], nums?.[1] || 0); + + const results = [nums[0], Math.max(nums[0], nums[1])]; + const not1results = [0, nums[1]]; + for (let i = 2; i < nums.length; i++) { + results[i] = Math.max(results[i - 1], results[i - 2] + nums[i]); + not1results[i] = Math.max(not1results[i - 1], not1results[i - 2] + nums[i]); + } + + return Math.max(results[nums.length - 2], not1results[nums.length - 1]); +}; From 4f0829312ce1771d9c3d0bb861e6b97fbc481201 Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 26 Nov 2024 21:22:54 +0900 Subject: [PATCH 48/49] 207 / Course Schedule / Medium / - --- oris8/207_course-schedule.js | 50 ++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 oris8/207_course-schedule.js diff --git a/oris8/207_course-schedule.js b/oris8/207_course-schedule.js new file mode 100644 index 0000000..6aaaf3c --- /dev/null +++ b/oris8/207_course-schedule.js @@ -0,0 +1,50 @@ +// 207 / Course Schedule / Medium / - +/** + * @param {number} numCourses + * @param {number[][]} prerequisites + * @return {boolean} + */ + +/** + * @param {number} numCourses + * @param {number[][]} prerequisites + * @return {boolean} + */ +var canFinish = function (numCourses, prerequisites) { + const graph = new Map(); + + // 그래프 생성 + for (let i = 0; i < numCourses; i++) { + graph.set(i, []); + } + + for (const [course, prereq] of prerequisites) { + graph.get(prereq).push(course); + } + + // 방문 상태 관리 + const visited = new Set(); // 현재 DFS 방문 중인 노드 + const completed = new Set(); // 이미 처리 완료된 노드 + + // 사이클 탐지 함수 + const dfs = (course) => { + if (visited.has(course)) return false; // 사이클 발견 + if (completed.has(course)) return true; // 이미 확인된 경우 + + visited.add(course); // 현재 노드 방문 중 + for (const nextCourse of graph.get(course)) { + if (!dfs(nextCourse)) return false; // 다음 코스에서 사이클 발견 + } + visited.delete(course); // 탐색 완료 후 제거 + completed.add(course); // 완료된 노드로 기록 + + return true; + }; + + // 각 강좌에 대해 DFS 실행 + for (let i = 0; i < numCourses; i++) { + if (!dfs(i)) return false; // 사이클이 존재하면 false 반환 + } + + return true; // 모든 강좌를 완료할 수 있음 +}; From fee7432e93d90da8c52a763bcda63ff25ab10c7c Mon Sep 17 00:00:00 2001 From: eprnf Date: Tue, 26 Nov 2024 21:23:10 +0900 Subject: [PATCH 49/49] 150 / Evaluate Reverse Polish Notation / Medium / 36m 44s --- oris8/150_evaluate-reverse-polish-notation.js | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 oris8/150_evaluate-reverse-polish-notation.js diff --git a/oris8/150_evaluate-reverse-polish-notation.js b/oris8/150_evaluate-reverse-polish-notation.js new file mode 100644 index 0000000..57d3722 --- /dev/null +++ b/oris8/150_evaluate-reverse-polish-notation.js @@ -0,0 +1,29 @@ +/** + * + * 150 / Evaluate Reverse Polish Notation / Medium / 36m 44s + * + * @param {string[]} tokens + * @return {number} + */ +var evalRPN = function (tokens) { + const operators = { + "+": (a, b) => a + b, + "-": (a, b) => a - b, + "*": (a, b) => a * b, + "/": (a, b) => Math.trunc(a / b), + }; + + const stack = []; + + for (const token of tokens) { + if (operators?.[token]) { + const b = stack.pop(); + const a = stack.pop(); + stack.push(operators[token](a, b)); + } else { + stack.push(+token); + } + } + + return stack.pop(); +};