From 0ca4ca3cfed49a6bbd3911d02a3c59afe5b8be5a Mon Sep 17 00:00:00 2001 From: "dd_._._bb" Date: Mon, 6 Jan 2025 07:43:00 +0900 Subject: [PATCH 1/9] Best Time to Buy and Sell Stock --- .../lledellebell.js | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 best-time-to-buy-and-sell-stock/lledellebell.js diff --git a/best-time-to-buy-and-sell-stock/lledellebell.js b/best-time-to-buy-and-sell-stock/lledellebell.js new file mode 100644 index 000000000..16babce02 --- /dev/null +++ b/best-time-to-buy-and-sell-stock/lledellebell.js @@ -0,0 +1,41 @@ +/* +Time complexity: O(n) +Space complexity: O(1) + +문제 설명: +- 주어진 배열 `prices`에서, i <= j인 두 인덱스 i, j에 대해 prices[j] - prices[i]를 최대화해야 합니다. +- 즉, 한 번의 매수와 한 번의 매도를 통해 얻을 수 있는 최대 이익을 계산합니다. +- 매수는 매도보다 반드시 먼저 이루어져야 합니다. + +알고리즘 설명: +1. 배열을 왼쪽에서 오른쪽으로 한 번 순회합니다. +2. 현재 주식 가격이 `min_price`보다 작으면, `min_price`를 갱신합니다. + - `min_price`는 현재까지의 최소 매수 가격을 의미합니다. +3. 현재 주식 가격에서 `min_price`를 뺀 값(현재 이익)이 `max_profit`보다 크면, `max_profit`을 갱신합니다. + - `max_profit`은 현재까지의 최대 이익을 의미합니다. +4. 배열 순회가 끝난 후, `max_profit`을 반환합니다. + +시간 복잡도: +- 배열을 한 번만 순회하므로 O(n)입니다. + +공간 복잡도: +- 추가적인 배열이나 데이터 구조를 사용하지 않고, 두 개의 변수(`min_price`, `max_profit`)만 사용하므로 O(1)입니다. +*/ + +function maxProfit(prices) { + let min_price = Infinity; // 초기 최소값을 무한대로 설정 (어떤 값과 비교해도 갱신되도록 설정) + let max_profit = 0; // 초기 최대 이익은 0 (이익이 없을 경우에도 0을 반환해야 함) + + // 배열을 순회하며 최소 매수 가격과 최대 이익을 계산 + for (let price of prices) { + if (price < min_price) { + // 현재 주식 가격이 최소 매수 가격보다 작으면 최소 매수 가격 갱신 + min_price = price; + } else if (price - min_price > max_profit) { + // 현재 주식 가격에서 최소 매수 가격을 뺀 값(현재 이익)이 최대 이익보다 크면 최대 이익 갱신 + max_profit = price - min_price; + } + } + + return max_profit; // 최대 이익 반환 +} \ No newline at end of file From b604d4c0ff0dadd2ce5d37d895944a495fb54c9d Mon Sep 17 00:00:00 2001 From: "dd_._._bb" Date: Mon, 6 Jan 2025 07:59:19 +0900 Subject: [PATCH 2/9] =?UTF-8?q?chore:=20=ED=8C=8C=EC=9D=BC=EC=9D=98=20?= =?UTF-8?q?=EB=A7=88=EC=A7=80=EB=A7=89=EC=97=90=20=EA=B0=9C=ED=96=89?= =?UTF-8?q?=EB=AC=B8=EC=9E=90=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- best-time-to-buy-and-sell-stock/lledellebell.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/best-time-to-buy-and-sell-stock/lledellebell.js b/best-time-to-buy-and-sell-stock/lledellebell.js index 16babce02..9592fc16f 100644 --- a/best-time-to-buy-and-sell-stock/lledellebell.js +++ b/best-time-to-buy-and-sell-stock/lledellebell.js @@ -38,4 +38,4 @@ function maxProfit(prices) { } return max_profit; // 최대 이익 반환 -} \ No newline at end of file +} From 3ae91359fc56d96091fccb232c601d336e01e34e Mon Sep 17 00:00:00 2001 From: "dd_._._bb" Date: Mon, 6 Jan 2025 08:03:42 +0900 Subject: [PATCH 3/9] =?UTF-8?q?chore:=20=EC=A3=BC=EC=84=9D=20=EC=8A=A4?= =?UTF-8?q?=ED=83=80=EC=9D=BC=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lledellebell.js | 45 ++++++++----------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/best-time-to-buy-and-sell-stock/lledellebell.js b/best-time-to-buy-and-sell-stock/lledellebell.js index 9592fc16f..7dec3935b 100644 --- a/best-time-to-buy-and-sell-stock/lledellebell.js +++ b/best-time-to-buy-and-sell-stock/lledellebell.js @@ -1,30 +1,23 @@ -/* -Time complexity: O(n) -Space complexity: O(1) - -문제 설명: -- 주어진 배열 `prices`에서, i <= j인 두 인덱스 i, j에 대해 prices[j] - prices[i]를 최대화해야 합니다. -- 즉, 한 번의 매수와 한 번의 매도를 통해 얻을 수 있는 최대 이익을 계산합니다. -- 매수는 매도보다 반드시 먼저 이루어져야 합니다. - -알고리즘 설명: -1. 배열을 왼쪽에서 오른쪽으로 한 번 순회합니다. -2. 현재 주식 가격이 `min_price`보다 작으면, `min_price`를 갱신합니다. - - `min_price`는 현재까지의 최소 매수 가격을 의미합니다. -3. 현재 주식 가격에서 `min_price`를 뺀 값(현재 이익)이 `max_profit`보다 크면, `max_profit`을 갱신합니다. - - `max_profit`은 현재까지의 최대 이익을 의미합니다. -4. 배열 순회가 끝난 후, `max_profit`을 반환합니다. - -시간 복잡도: -- 배열을 한 번만 순회하므로 O(n)입니다. - -공간 복잡도: -- 추가적인 배열이나 데이터 구조를 사용하지 않고, 두 개의 변수(`min_price`, `max_profit`)만 사용하므로 O(1)입니다. -*/ - +/** + * 주어진 주식 가격 배열에서 한 번의 매수와 한 번의 매도를 통해 얻을 수 있는 최대 이익을 계산합니다. + * 매수는 매도보다 반드시 먼저 이루어져야 합니다. + * + * @param {number[]} prices - 각 날짜별 주식 가격을 나타내는 배열 + * @returns {number} 최대 이익 (이익을 낼 수 없는 경우 0 반환) + * + * @example + * maxProfit([7, 1, 5, 3, 6, 4]); // 5 (2일차에 매수하고 5일차에 매도) + * maxProfit([7, 6, 4, 3, 1]); // 0 (이익을 낼 수 없음) + * + * @description + * - 시간 복잡도: O(n) + * 배열을 한 번 순회하며 각 요소에 대해 상수 시간 연산만 수행합니다. + * - 공간 복잡도: O(1) + * 추가적인 배열이나 데이터 구조를 사용하지 않고, 두 개의 변수만 사용합니다. + */ function maxProfit(prices) { - let min_price = Infinity; // 초기 최소값을 무한대로 설정 (어떤 값과 비교해도 갱신되도록 설정) - let max_profit = 0; // 초기 최대 이익은 0 (이익이 없을 경우에도 0을 반환해야 함) + let min_price = Infinity; // 현재까지의 최소 매수 가격 (초기값은 무한대) + let max_profit = 0; // 현재까지의 최대 이익 (초기값은 0) // 배열을 순회하며 최소 매수 가격과 최대 이익을 계산 for (let price of prices) { From 05a4fea07ad47b9c5943c513d73f28541c48012e Mon Sep 17 00:00:00 2001 From: "dd_._._bb" Date: Mon, 6 Jan 2025 09:28:55 +0900 Subject: [PATCH 4/9] Group Anagrams --- .../lledellebell.js | 5 ++ group-anagrams/lledellebell.ts | 50 +++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 group-anagrams/lledellebell.ts diff --git a/best-time-to-buy-and-sell-stock/lledellebell.js b/best-time-to-buy-and-sell-stock/lledellebell.js index 7dec3935b..5d3e219e2 100644 --- a/best-time-to-buy-and-sell-stock/lledellebell.js +++ b/best-time-to-buy-and-sell-stock/lledellebell.js @@ -1,4 +1,6 @@ /** + * + * @problem * 주어진 주식 가격 배열에서 한 번의 매수와 한 번의 매도를 통해 얻을 수 있는 최대 이익을 계산합니다. * 매수는 매도보다 반드시 먼저 이루어져야 합니다. * @@ -32,3 +34,6 @@ function maxProfit(prices) { return max_profit; // 최대 이익 반환 } + +console.log(maxProfit([7, 1, 5, 3, 6, 4])); // 5 +console.log(maxProfit([7, 6, 4, 3, 1])); // 0 diff --git a/group-anagrams/lledellebell.ts b/group-anagrams/lledellebell.ts new file mode 100644 index 000000000..56da5ae82 --- /dev/null +++ b/group-anagrams/lledellebell.ts @@ -0,0 +1,50 @@ +/** + * + * @problem + * 문자열 배열이 주어졌을 때, 애너그램끼리 그룹화해야 합니다. + * + * (참고) + * 애너그램(Anagram)이란 단어를 구성하는 문자의 순서를 바꿔서 다른 단어를 만드는 것을 의미합니다. + * 예를 들어, "eat", "tea", "ate"는 모두 같은 문자로 구성되어 있으므로 애너그램입니다. + * + * @param {string[]} strs - 입력 문자열 배열 + * @returns {string[][]} 애너그램 그룹으로 묶인 2차원 문자열 배열 + * + * @example + * groupAnagrams(["eat", "tea", "tan", "ate", "nat", "bat"]); // [["bat"], ["nat", "tan"], ["ate", "eat", "tea"]] + * groupAnagrams([""]); // [[""]] + * groupAnagrams(["a"]); // [["a"]] + * + * @description + * - 시간 복잡도: O(N * K log K) + * ㄴ N: 입력 문자열 배열의 길이 + * ㄴ K: 각 문자열의 평균 길이 + * 각 문자열을 정렬하는 데 O(K log K)의 시간이 소요되며, 이를 N번 반복합니다. + * - 공간 복잡도: O(N * K) + * 해시맵에 저장되는 키와 값의 총 길이에 비례합니다. + */ +function groupAnagrams(strs: string[]): string[][] { + // 애너그램 그룹을 저장할 해시맵 + const anagrams: Record = {}; + + // 입력 문자열 배열을 순회 + for (const str of strs) { + // 문자열을 정렬하여 애너그램 그룹의 키 생성 + const key = str.split('').sort().join(''); + + // 키가 해시맵에 없으면 초기화 + if (!anagrams[key]) { + anagrams[key] = []; + } + + // 해당 키에 문자열 추가 + anagrams[key].push(str); + } + + // 해시맵의 값들만 반환 (애너그램 그룹) + return Object.values(anagrams); +} + +console.log(groupAnagrams(["eat", "tea", "tan", "ate", "nat", "bat"])); // [["bat"], ["nat", "tan"], ["ate", "eat", "tea"]] +console.log(groupAnagrams([""])); // [[""]] +console.log(groupAnagrams(["a"])); // [["a"]] From 5a677bd744e734cd24d84ccc6d5301cb73211505 Mon Sep 17 00:00:00 2001 From: "dd_._._bb" Date: Mon, 6 Jan 2025 14:10:24 +0900 Subject: [PATCH 5/9] Encode and Decode Strings --- encode-and-decode-strings/lledellebell.js | 67 +++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 encode-and-decode-strings/lledellebell.js diff --git a/encode-and-decode-strings/lledellebell.js b/encode-and-decode-strings/lledellebell.js new file mode 100644 index 000000000..90946861c --- /dev/null +++ b/encode-and-decode-strings/lledellebell.js @@ -0,0 +1,67 @@ +/** + * + * @problem + * 문자열 배열을 단일 문자열로 인코딩하고, + * 다시 원래의 문자열 배열로 디코딩하는 기능을 만들어야 합니다. + * + * @example + * const encoded = encode(["hello", "world"]); + * console.log(encoded); // "5?hello5?world" + * const decoded = decode(encoded); + * console.log(decoded); // ["hello", "world"] + * + * @description + * - 시간 복잡도: + * ㄴ encode: O(n) (n은 문자열 배열의 총 길이) + * ㄴ decode: O(n) (n은 인코딩된 문자열의 길이) + * - 공간 복잡도: + * ㄴ encode: O(1) (추가 메모리 사용 없음) + * ㄴ decode: O(1) (결과 배열을 제외한 추가 메모리 사용 없음) + */ + +/** + * @param {string[]} strs - 인코딩할 문자열 배열 + * @returns {string} - 인코딩된 문자열 + */ +const encode = (strs) => { + let encoded = ''; + for (const str of strs) { + // 문자열을 "길이?문자열" 형식으로 추가 + encoded += `${str.length}?${str}`; + } + return encoded; +}; + +/** + * @param {string} s - 인코딩된 문자열 + * @returns {string[]} - 디코딩된 문자열 배열 + */ +const decode = (s) => { + const result = []; + let i = 0; + + while (i < s.length) { + // 현재 위치에서 숫자(길이)를 읽음 + let length = 0; + while (s[i] !== '?') { + length = length * 10 + (s[i].charCodeAt(0) - '0'.charCodeAt(0)); // 숫자 계산 + i++; + } + + // '?' 이후의 문자열을 추출 + i++; // '?'를 건너뜀 + const str = s.substring(i, i + length); + result.push(str); + + // 다음 문자열로 이동 + i += length; + } + + return result; +}; + +const encoded = encode(["hello", "world"]); +console.log(encoded); // "5?hello5?world" + +const decoded = decode(encoded); +console.log(decoded); // ["hello", "world"] From 1a8ba736f2830ae4ae3c3a7c94c852679f6fdb02 Mon Sep 17 00:00:00 2001 From: deep Date: Mon, 6 Jan 2025 21:15:09 +0900 Subject: [PATCH 6/9] Implement Trie (Prefix Tree) --- implement-trie-prefix-tree/lledellebell.js | 115 +++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 implement-trie-prefix-tree/lledellebell.js diff --git a/implement-trie-prefix-tree/lledellebell.js b/implement-trie-prefix-tree/lledellebell.js new file mode 100644 index 000000000..7a499abac --- /dev/null +++ b/implement-trie-prefix-tree/lledellebell.js @@ -0,0 +1,115 @@ +/** + * @problem + * Trie를 구현합니다. + * - 메모리 사용량을 최적화하면서 정확한 검색 결과를 보장해야 합니다. + * + * @example + * const trie = new Trie(); + * trie.insert("apple"); // undefined + * trie.search("apple"); // true + * trie.search("app"); // false + * trie.startsWith("app"); // true + * trie.insert("app"); // undefined + * trie.search("app"); // true + * + * @description + * - 시간복잡도: + * ㄴ insert: O(m) (m은 단어 길이) + * ㄴ search: O(m) (m은 단어 길이) + * ㄴ startsWith: O(m) (m은 접두사 길이) + * - 공간복잡도: O(ALPHABET_SIZE * m * n) + * ㄴ ALPHABET_SIZE: 문자열의 알파벳 수 (영문의 경우 26) + * ㄴ m: 단어의 평균 길이 + */ +class TrieNode { + constructor() { + // 각 문자를 키로 하고 자식 노드를 값으로 하는 객체 + this.children = {}; + // 현재 노드가 단어의 마지막 문자인지 표시하는 플래그 + this.isEndOfWord = false; + } +} + +class Trie { + constructor() { + // 빈 문자열을 나타내는 루트 노드 생성 + this.root = new TrieNode(); + } + + /** + * 단어를 Trie에 삽입하는 메서드 + * @param {string} word - 삽입할 단어 + */ + insert(word) { + // 루트 노드부터 시작 + let node = this.root; + + // 단어의 각 문자를 순회 + for (let i = 0; i < word.length; i++) { + const char = word[i]; + // 현재 문자에 대한 노드가 없으면 새로 생성 + if (!(char in node.children)) { + node.children[char] = new TrieNode(); + } + // 다음 문자를 처리하기 위해 자식 노드로 이동 + node = node.children[char]; + } + // 단어의 마지막 문자임을 표시 + node.isEndOfWord = true; + } + + + /** + * 정확한 단어가 존재하는지 검색하는 메서드 + * @param {string} word - 검색할 단어 + * @returns {boolean} - 단어 존재 여부 + */ + search(word) { + // 단어를 찾아 마지막 노드를 반환 + const node = this._traverse(word); + // 단어가 존재하고 해당 노드가 단어의 끝인 경우에만 true 반환 + return node !== null && node.isEndOfWord; + } + + /** + * 주어진 접두사로 시작하는 단어가 존재하는지 검색하는 메서드 + * @param {string} prefix - 검색할 접두사 + * @returns {boolean} - 접두사로 시작하는 단어 존재 여부 + */ + startsWith(prefix) { + // 접두사에 해당하는 노드가 존재하는지만 확인 + return this._traverse(prefix) !== null; + } + + /** + * 문자열을 따라가며 마지막 노드를 반환하는 내부 헬퍼 메서드 + * @param {string} str - 탐색할 문자열 + * @returns {TrieNode|null} - 마지막 문자에 해당하는 노드 또는 null + * @private + */ + _traverse(str) { + // 루트 노드부터 시작 + let node = this.root; + + // 문자열의 각 문자를 순회 + for (let i = 0; i < str.length; i++) { + const char = str[i]; + // 현재 문자에 대한 노드가 없으면 null 반환 + if (!(char in node.children)) { + return null; + } + // 다음 문자를 처리하기 위해 자식 노드로 이동 + node = node.children[char]; + } + // 마지막 노드 반환 + return node; + } +} + +const trie = new Trie(); +console.log(trie.insert("apple")); // undefined +console.log(trie.search("apple")); // true +console.log(trie.search("app")); // false +console.log(trie.startsWith("app")); // true +console.log(trie.insert("app")); // undefined +console.log(trie.search("app")); // true From 1d5739383695584e574a150a5ecddb55d6738418 Mon Sep 17 00:00:00 2001 From: deep Date: Mon, 6 Jan 2025 22:15:17 +0900 Subject: [PATCH 7/9] Word Break --- word-break/lledellebell.js | 74 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 word-break/lledellebell.js diff --git a/word-break/lledellebell.js b/word-break/lledellebell.js new file mode 100644 index 000000000..282ef84c9 --- /dev/null +++ b/word-break/lledellebell.js @@ -0,0 +1,74 @@ +/** + * @problem + * 주어진 문자열 s가 단어 사전 wordDict에 포함된 단어들로만 구성될 수 있는지 확인하는 문제입니다. + * 단어 사전의 단어들은 여러 번 사용할 수 있으며, 문자열 s를 완전히 나눌 수 있어야 합니다. + * + * @constraints + * - 1 <= s.length <= 300 + * - 1 <= wordDict.length <= 1000 + * - 1 <= wordDict[i].length <= 20 + * - s와 wordDict[i]는 모두 소문자 알파벳으로만 구성됩니다. + * + * @param {string} s - 주어진 문자열 + * @param {string[]} wordDict - 단어 사전 + * @returns {boolean} 문자열 s가 단어 사전의 단어들로만 나눌 수 있는지 여부 + * + * @example + * - 예제 1: + * ㄴ Input: s = "leetcode", wordDict = ["leet", "code"] + * ㄴ Output: true + * ㄴ Explanation: "leetcode"는 "leet" + "code"로 나눌 수 있습니다. + * - 예제 2: + * ㄴ Input: s = "applepenapple", wordDict = ["apple", "pen"] + * ㄴ Output: true + * ㄴ Explanation: "applepenapple"는 "apple" + "pen" + "apple"로 나눌 수 있습니다. + * - 예제 3: + * ㄴ Input: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"] + * ㄴ Output: false + * ㄴ Explanation: "catsandog"는 wordDict의 단어들로 나눌 수 없습니다. + * + * @description + * - 시간 복잡도: O(n^2) + * ㄴ 외부 반복문: 문자열 s의 길이 n에 대해 1부터 n까지 반복 (O(n)) + * ㄴ 내부 반복문: 각 i에 대해 최대 i번 반복 (O(n)) + * ㄴ substring 및 Set 검색: O(1) (substring은 내부적으로 O(k)이지만, k는 최대 단어 길이로 간주) + * ㄴ 결과적으로 O(n^2)의 시간 복잡도를 가짐 + * - 공간 복잡도: O(n + m) + * ㄴ dp 배열의 크기: s의 길이 n + 1 (O(n)) + * ㄴ wordSet: wordDict의 단어 개수에 비례 (O(m), m은 wordDict의 단어 수) + */ +function wordBreak(s, wordDict) { + // wordDict를 Set으로 변환하여 검색 속도를 O(1)로 만듦 + const wordSet = new Set(wordDict); + + // dp 배열 생성: dp[i]는 s의 처음부터 i번째 문자까지가 wordDict의 단어들로 나눌 수 있는지를 나타냄 + const dp = new Array(s.length + 1).fill(false); + dp[0] = true; // 빈 문자열은 항상 나눌 수 있음 + + // i는 문자열의 끝 인덱스를 나타냄 + for (let i = 1; i <= s.length; i++) { + // j는 문자열의 시작 인덱스를 나타냄 + for (let j = 0; j < i; j++) { + // dp[j]가 true이고, s[j:i]가 wordSet에 포함되어 있다면 + if (dp[j] && wordSet.has(s.substring(j, i))) { + dp[i] = true; // dp[i]를 true로 설정 + break; // 더 이상 확인할 필요 없음 + } + } + } + + // dp[s.length]가 true라면 문자열 s를 wordDict의 단어들로 나눌 수 있음 + return dp[s.length]; +} + +const s1 = "leetcode"; +const wordDict1 = ["leet", "code"]; +console.log(wordBreak(s1, wordDict1)); // true + +const s2 = "applepenapple"; +const wordDict2 = ["apple", "pen"]; +console.log(wordBreak(s2, wordDict2)); // true + +const s3 = "catsandog"; +const wordDict3 = ["cats", "dog", "sand", "and", "cat"]; +console.log(wordBreak(s3, wordDict3)); // false From cfb2c82c18951436ed1ba449dde3bad071cb0e37 Mon Sep 17 00:00:00 2001 From: "dd_._._bb" Date: Wed, 8 Jan 2025 08:38:07 +0900 Subject: [PATCH 8/9] refactor: Object to Map --- group-anagrams/lledellebell.ts | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/group-anagrams/lledellebell.ts b/group-anagrams/lledellebell.ts index 56da5ae82..6c21b95c8 100644 --- a/group-anagrams/lledellebell.ts +++ b/group-anagrams/lledellebell.ts @@ -16,6 +16,11 @@ * groupAnagrams(["a"]); // [["a"]] * * @description + * - 각 문자열을 정렬하여 동일한 문자를 가진 문자열들을 그룹화합니다. + * - 정렬된 문자열을 키로 사용하여 해시맵(Map)에 저장합니다. + * - 최종적으로 해시맵의 값들만 추출하여 반환합니다. + * + * @complexity * - 시간 복잡도: O(N * K log K) * ㄴ N: 입력 문자열 배열의 길이 * ㄴ K: 각 문자열의 평균 길이 @@ -24,25 +29,17 @@ * 해시맵에 저장되는 키와 값의 총 길이에 비례합니다. */ function groupAnagrams(strs: string[]): string[][] { - // 애너그램 그룹을 저장할 해시맵 - const anagrams: Record = {}; + const anagrams = new Map(); - // 입력 문자열 배열을 순회 for (const str of strs) { - // 문자열을 정렬하여 애너그램 그룹의 키 생성 const key = str.split('').sort().join(''); - - // 키가 해시맵에 없으면 초기화 - if (!anagrams[key]) { - anagrams[key] = []; + if (!anagrams.has(key)) { + anagrams.set(key, []); } - - // 해당 키에 문자열 추가 - anagrams[key].push(str); + anagrams.get(key)!.push(str); } - // 해시맵의 값들만 반환 (애너그램 그룹) - return Object.values(anagrams); + return Array.from(anagrams.values()); } console.log(groupAnagrams(["eat", "tea", "tan", "ate", "nat", "bat"])); // [["bat"], ["nat", "tan"], ["ate", "eat", "tea"]] From acacff5eff407a9606d4e516c2b118660a761c77 Mon Sep 17 00:00:00 2001 From: "dd_._._bb" Date: Wed, 8 Jan 2025 20:06:34 +0900 Subject: [PATCH 9/9] =?UTF-8?q?chore:=20@constraints=20=EB=82=B4=EC=9A=A9?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- best-time-to-buy-and-sell-stock/lledellebell.js | 6 +++++- encode-and-decode-strings/lledellebell.js | 2 +- group-anagrams/lledellebell.ts | 5 +++++ implement-trie-prefix-tree/lledellebell.js | 7 ++++++- word-break/lledellebell.js | 2 +- 5 files changed, 18 insertions(+), 4 deletions(-) diff --git a/best-time-to-buy-and-sell-stock/lledellebell.js b/best-time-to-buy-and-sell-stock/lledellebell.js index 5d3e219e2..23809c742 100644 --- a/best-time-to-buy-and-sell-stock/lledellebell.js +++ b/best-time-to-buy-and-sell-stock/lledellebell.js @@ -3,6 +3,10 @@ * @problem * 주어진 주식 가격 배열에서 한 번의 매수와 한 번의 매도를 통해 얻을 수 있는 최대 이익을 계산합니다. * 매수는 매도보다 반드시 먼저 이루어져야 합니다. + * + * @constraints + * - 1 <= prices.length <= 105 + * - 0 <= prices[i] <= 104 * * @param {number[]} prices - 각 날짜별 주식 가격을 나타내는 배열 * @returns {number} 최대 이익 (이익을 낼 수 없는 경우 0 반환) @@ -11,7 +15,7 @@ * maxProfit([7, 1, 5, 3, 6, 4]); // 5 (2일차에 매수하고 5일차에 매도) * maxProfit([7, 6, 4, 3, 1]); // 0 (이익을 낼 수 없음) * - * @description + * @complexity * - 시간 복잡도: O(n) * 배열을 한 번 순회하며 각 요소에 대해 상수 시간 연산만 수행합니다. * - 공간 복잡도: O(1) diff --git a/encode-and-decode-strings/lledellebell.js b/encode-and-decode-strings/lledellebell.js index 90946861c..09346cf3b 100644 --- a/encode-and-decode-strings/lledellebell.js +++ b/encode-and-decode-strings/lledellebell.js @@ -10,7 +10,7 @@ * const decoded = decode(encoded); * console.log(decoded); // ["hello", "world"] * - * @description + * @complexity * - 시간 복잡도: * ㄴ encode: O(n) (n은 문자열 배열의 총 길이) * ㄴ decode: O(n) (n은 인코딩된 문자열의 길이) diff --git a/group-anagrams/lledellebell.ts b/group-anagrams/lledellebell.ts index 6c21b95c8..9b55c7b0a 100644 --- a/group-anagrams/lledellebell.ts +++ b/group-anagrams/lledellebell.ts @@ -6,6 +6,11 @@ * (참고) * 애너그램(Anagram)이란 단어를 구성하는 문자의 순서를 바꿔서 다른 단어를 만드는 것을 의미합니다. * 예를 들어, "eat", "tea", "ate"는 모두 같은 문자로 구성되어 있으므로 애너그램입니다. + * + * @constraints + * - 1 <= strs.length <= 104 + * - 0 <= strs[i].length <= 100 + * - strs[i]는 소문자 알파벳으로만 구성됩니다. * * @param {string[]} strs - 입력 문자열 배열 * @returns {string[][]} 애너그램 그룹으로 묶인 2차원 문자열 배열 diff --git a/implement-trie-prefix-tree/lledellebell.js b/implement-trie-prefix-tree/lledellebell.js index 7a499abac..5b0b061ae 100644 --- a/implement-trie-prefix-tree/lledellebell.js +++ b/implement-trie-prefix-tree/lledellebell.js @@ -3,6 +3,11 @@ * Trie를 구현합니다. * - 메모리 사용량을 최적화하면서 정확한 검색 결과를 보장해야 합니다. * + * @constraints + * - word와 prefix의 길이는 최소 1, 최대 2000입니다. + * - word와 prefix는 소문자 영어 알파벳(a-z)만으로 구성됩니다. + * - insert, search, startsWith 함수 호출은 총 30,000번을 넘지 않습니다. + * * @example * const trie = new Trie(); * trie.insert("apple"); // undefined @@ -12,7 +17,7 @@ * trie.insert("app"); // undefined * trie.search("app"); // true * - * @description + * @complexity * - 시간복잡도: * ㄴ insert: O(m) (m은 단어 길이) * ㄴ search: O(m) (m은 단어 길이) diff --git a/word-break/lledellebell.js b/word-break/lledellebell.js index 282ef84c9..1d090875f 100644 --- a/word-break/lledellebell.js +++ b/word-break/lledellebell.js @@ -27,7 +27,7 @@ * ㄴ Output: false * ㄴ Explanation: "catsandog"는 wordDict의 단어들로 나눌 수 없습니다. * - * @description + * @complexity * - 시간 복잡도: O(n^2) * ㄴ 외부 반복문: 문자열 s의 길이 n에 대해 1부터 n까지 반복 (O(n)) * ㄴ 내부 반복문: 각 i에 대해 최대 i번 반복 (O(n))