Skip to content

Commit 6f7243a

Browse files
committed
2 parents cfb2c82 + 1d57393 commit 6f7243a

File tree

2 files changed

+189
-0
lines changed

2 files changed

+189
-0
lines changed
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/**
2+
* @problem
3+
* Trie๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
4+
* - ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์„ ์ตœ์ ํ™”ํ•˜๋ฉด์„œ ์ •ํ™•ํ•œ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์žฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
5+
*
6+
* @example
7+
* const trie = new Trie();
8+
* trie.insert("apple"); // undefined
9+
* trie.search("apple"); // true
10+
* trie.search("app"); // false
11+
* trie.startsWith("app"); // true
12+
* trie.insert("app"); // undefined
13+
* trie.search("app"); // true
14+
*
15+
* @description
16+
* - ์‹œ๊ฐ„๋ณต์žก๋„:
17+
* ใ„ด insert: O(m) (m์€ ๋‹จ์–ด ๊ธธ์ด)
18+
* ใ„ด search: O(m) (m์€ ๋‹จ์–ด ๊ธธ์ด)
19+
* ใ„ด startsWith: O(m) (m์€ ์ ‘๋‘์‚ฌ ๊ธธ์ด)
20+
* - ๊ณต๊ฐ„๋ณต์žก๋„: O(ALPHABET_SIZE * m * n)
21+
* ใ„ด ALPHABET_SIZE: ๋ฌธ์ž์—ด์˜ ์•ŒํŒŒ๋ฒณ ์ˆ˜ (์˜๋ฌธ์˜ ๊ฒฝ์šฐ 26)
22+
* ใ„ด m: ๋‹จ์–ด์˜ ํ‰๊ท  ๊ธธ์ด
23+
*/
24+
class TrieNode {
25+
constructor() {
26+
// ๊ฐ ๋ฌธ์ž๋ฅผ ํ‚ค๋กœ ํ•˜๊ณ  ์ž์‹ ๋…ธ๋“œ๋ฅผ ๊ฐ’์œผ๋กœ ํ•˜๋Š” ๊ฐ์ฒด
27+
this.children = {};
28+
// ํ˜„์žฌ ๋…ธ๋“œ๊ฐ€ ๋‹จ์–ด์˜ ๋งˆ์ง€๋ง‰ ๋ฌธ์ž์ธ์ง€ ํ‘œ์‹œํ•˜๋Š” ํ”Œ๋ž˜๊ทธ
29+
this.isEndOfWord = false;
30+
}
31+
}
32+
33+
class Trie {
34+
constructor() {
35+
// ๋นˆ ๋ฌธ์ž์—ด์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฃจํŠธ ๋…ธ๋“œ ์ƒ์„ฑ
36+
this.root = new TrieNode();
37+
}
38+
39+
/**
40+
* ๋‹จ์–ด๋ฅผ Trie์— ์‚ฝ์ž…ํ•˜๋Š” ๋ฉ”์„œ๋“œ
41+
* @param {string} word - ์‚ฝ์ž…ํ•  ๋‹จ์–ด
42+
*/
43+
insert(word) {
44+
// ๋ฃจํŠธ ๋…ธ๋“œ๋ถ€ํ„ฐ ์‹œ์ž‘
45+
let node = this.root;
46+
47+
// ๋‹จ์–ด์˜ ๊ฐ ๋ฌธ์ž๋ฅผ ์ˆœํšŒ
48+
for (let i = 0; i < word.length; i++) {
49+
const char = word[i];
50+
// ํ˜„์žฌ ๋ฌธ์ž์— ๋Œ€ํ•œ ๋…ธ๋“œ๊ฐ€ ์—†์œผ๋ฉด ์ƒˆ๋กœ ์ƒ์„ฑ
51+
if (!(char in node.children)) {
52+
node.children[char] = new TrieNode();
53+
}
54+
// ๋‹ค์Œ ๋ฌธ์ž๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์ž์‹ ๋…ธ๋“œ๋กœ ์ด๋™
55+
node = node.children[char];
56+
}
57+
// ๋‹จ์–ด์˜ ๋งˆ์ง€๋ง‰ ๋ฌธ์ž์ž„์„ ํ‘œ์‹œ
58+
node.isEndOfWord = true;
59+
}
60+
61+
62+
/**
63+
* ์ •ํ™•ํ•œ ๋‹จ์–ด๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ๊ฒ€์ƒ‰ํ•˜๋Š” ๋ฉ”์„œ๋“œ
64+
* @param {string} word - ๊ฒ€์ƒ‰ํ•  ๋‹จ์–ด
65+
* @returns {boolean} - ๋‹จ์–ด ์กด์žฌ ์—ฌ๋ถ€
66+
*/
67+
search(word) {
68+
// ๋‹จ์–ด๋ฅผ ์ฐพ์•„ ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ๋ฅผ ๋ฐ˜ํ™˜
69+
const node = this._traverse(word);
70+
// ๋‹จ์–ด๊ฐ€ ์กด์žฌํ•˜๊ณ  ํ•ด๋‹น ๋…ธ๋“œ๊ฐ€ ๋‹จ์–ด์˜ ๋์ธ ๊ฒฝ์šฐ์—๋งŒ true ๋ฐ˜ํ™˜
71+
return node !== null && node.isEndOfWord;
72+
}
73+
74+
/**
75+
* ์ฃผ์–ด์ง„ ์ ‘๋‘์‚ฌ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋‹จ์–ด๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ๊ฒ€์ƒ‰ํ•˜๋Š” ๋ฉ”์„œ๋“œ
76+
* @param {string} prefix - ๊ฒ€์ƒ‰ํ•  ์ ‘๋‘์‚ฌ
77+
* @returns {boolean} - ์ ‘๋‘์‚ฌ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋‹จ์–ด ์กด์žฌ ์—ฌ๋ถ€
78+
*/
79+
startsWith(prefix) {
80+
// ์ ‘๋‘์‚ฌ์— ํ•ด๋‹นํ•˜๋Š” ๋…ธ๋“œ๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€๋งŒ ํ™•์ธ
81+
return this._traverse(prefix) !== null;
82+
}
83+
84+
/**
85+
* ๋ฌธ์ž์—ด์„ ๋”ฐ๋ผ๊ฐ€๋ฉฐ ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋‚ด๋ถ€ ํ—ฌํผ ๋ฉ”์„œ๋“œ
86+
* @param {string} str - ํƒ์ƒ‰ํ•  ๋ฌธ์ž์—ด
87+
* @returns {TrieNode|null} - ๋งˆ์ง€๋ง‰ ๋ฌธ์ž์— ํ•ด๋‹นํ•˜๋Š” ๋…ธ๋“œ ๋˜๋Š” null
88+
* @private
89+
*/
90+
_traverse(str) {
91+
// ๋ฃจํŠธ ๋…ธ๋“œ๋ถ€ํ„ฐ ์‹œ์ž‘
92+
let node = this.root;
93+
94+
// ๋ฌธ์ž์—ด์˜ ๊ฐ ๋ฌธ์ž๋ฅผ ์ˆœํšŒ
95+
for (let i = 0; i < str.length; i++) {
96+
const char = str[i];
97+
// ํ˜„์žฌ ๋ฌธ์ž์— ๋Œ€ํ•œ ๋…ธ๋“œ๊ฐ€ ์—†์œผ๋ฉด null ๋ฐ˜ํ™˜
98+
if (!(char in node.children)) {
99+
return null;
100+
}
101+
// ๋‹ค์Œ ๋ฌธ์ž๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์ž์‹ ๋…ธ๋“œ๋กœ ์ด๋™
102+
node = node.children[char];
103+
}
104+
// ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ ๋ฐ˜ํ™˜
105+
return node;
106+
}
107+
}
108+
109+
const trie = new Trie();
110+
console.log(trie.insert("apple")); // undefined
111+
console.log(trie.search("apple")); // true
112+
console.log(trie.search("app")); // false
113+
console.log(trie.startsWith("app")); // true
114+
console.log(trie.insert("app")); // undefined
115+
console.log(trie.search("app")); // true

โ€Žword-break/lledellebell.jsโ€Ž

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/**
2+
* @problem
3+
* ์ฃผ์–ด์ง„ ๋ฌธ์ž์—ด s๊ฐ€ ๋‹จ์–ด ์‚ฌ์ „ wordDict์— ํฌํ•จ๋œ ๋‹จ์–ด๋“ค๋กœ๋งŒ ๊ตฌ์„ฑ๋  ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค.
4+
* ๋‹จ์–ด ์‚ฌ์ „์˜ ๋‹จ์–ด๋“ค์€ ์—ฌ๋Ÿฌ ๋ฒˆ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ฌธ์ž์—ด s๋ฅผ ์™„์ „ํžˆ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
5+
*
6+
* @constraints
7+
* - 1 <= s.length <= 300
8+
* - 1 <= wordDict.length <= 1000
9+
* - 1 <= wordDict[i].length <= 20
10+
* - s์™€ wordDict[i]๋Š” ๋ชจ๋‘ ์†Œ๋ฌธ์ž ์•ŒํŒŒ๋ฒณ์œผ๋กœ๋งŒ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.
11+
*
12+
* @param {string} s - ์ฃผ์–ด์ง„ ๋ฌธ์ž์—ด
13+
* @param {string[]} wordDict - ๋‹จ์–ด ์‚ฌ์ „
14+
* @returns {boolean} ๋ฌธ์ž์—ด s๊ฐ€ ๋‹จ์–ด ์‚ฌ์ „์˜ ๋‹จ์–ด๋“ค๋กœ๋งŒ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€
15+
*
16+
* @example
17+
* - ์˜ˆ์ œ 1:
18+
* ใ„ด Input: s = "leetcode", wordDict = ["leet", "code"]
19+
* ใ„ด Output: true
20+
* ใ„ด Explanation: "leetcode"๋Š” "leet" + "code"๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
21+
* - ์˜ˆ์ œ 2:
22+
* ใ„ด Input: s = "applepenapple", wordDict = ["apple", "pen"]
23+
* ใ„ด Output: true
24+
* ใ„ด Explanation: "applepenapple"๋Š” "apple" + "pen" + "apple"๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
25+
* - ์˜ˆ์ œ 3:
26+
* ใ„ด Input: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
27+
* ใ„ด Output: false
28+
* ใ„ด Explanation: "catsandog"๋Š” wordDict์˜ ๋‹จ์–ด๋“ค๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
29+
*
30+
* @description
31+
* - ์‹œ๊ฐ„ ๋ณต์žก๋„: O(n^2)
32+
* ใ„ด ์™ธ๋ถ€ ๋ฐ˜๋ณต๋ฌธ: ๋ฌธ์ž์—ด s์˜ ๊ธธ์ด n์— ๋Œ€ํ•ด 1๋ถ€ํ„ฐ n๊นŒ์ง€ ๋ฐ˜๋ณต (O(n))
33+
* ใ„ด ๋‚ด๋ถ€ ๋ฐ˜๋ณต๋ฌธ: ๊ฐ i์— ๋Œ€ํ•ด ์ตœ๋Œ€ i๋ฒˆ ๋ฐ˜๋ณต (O(n))
34+
* ใ„ด substring ๋ฐ Set ๊ฒ€์ƒ‰: O(1) (substring์€ ๋‚ด๋ถ€์ ์œผ๋กœ O(k)์ด์ง€๋งŒ, k๋Š” ์ตœ๋Œ€ ๋‹จ์–ด ๊ธธ์ด๋กœ ๊ฐ„์ฃผ)
35+
* ใ„ด ๊ฒฐ๊ณผ์ ์œผ๋กœ O(n^2)์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ๊ฐ€์ง
36+
* - ๊ณต๊ฐ„ ๋ณต์žก๋„: O(n + m)
37+
* ใ„ด dp ๋ฐฐ์—ด์˜ ํฌ๊ธฐ: s์˜ ๊ธธ์ด n + 1 (O(n))
38+
* ใ„ด wordSet: wordDict์˜ ๋‹จ์–ด ๊ฐœ์ˆ˜์— ๋น„๋ก€ (O(m), m์€ wordDict์˜ ๋‹จ์–ด ์ˆ˜)
39+
*/
40+
function wordBreak(s, wordDict) {
41+
// wordDict๋ฅผ Set์œผ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ๊ฒ€์ƒ‰ ์†๋„๋ฅผ O(1)๋กœ ๋งŒ๋“ฆ
42+
const wordSet = new Set(wordDict);
43+
44+
// dp ๋ฐฐ์—ด ์ƒ์„ฑ: dp[i]๋Š” s์˜ ์ฒ˜์Œ๋ถ€ํ„ฐ i๋ฒˆ์งธ ๋ฌธ์ž๊นŒ์ง€๊ฐ€ wordDict์˜ ๋‹จ์–ด๋“ค๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋Š”์ง€๋ฅผ ๋‚˜ํƒ€๋ƒ„
45+
const dp = new Array(s.length + 1).fill(false);
46+
dp[0] = true; // ๋นˆ ๋ฌธ์ž์—ด์€ ํ•ญ์ƒ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์Œ
47+
48+
// i๋Š” ๋ฌธ์ž์—ด์˜ ๋ ์ธ๋ฑ์Šค๋ฅผ ๋‚˜ํƒ€๋ƒ„
49+
for (let i = 1; i <= s.length; i++) {
50+
// j๋Š” ๋ฌธ์ž์—ด์˜ ์‹œ์ž‘ ์ธ๋ฑ์Šค๋ฅผ ๋‚˜ํƒ€๋ƒ„
51+
for (let j = 0; j < i; j++) {
52+
// dp[j]๊ฐ€ true์ด๊ณ , s[j:i]๊ฐ€ wordSet์— ํฌํ•จ๋˜์–ด ์žˆ๋‹ค๋ฉด
53+
if (dp[j] && wordSet.has(s.substring(j, i))) {
54+
dp[i] = true; // dp[i]๋ฅผ true๋กœ ์„ค์ •
55+
break; // ๋” ์ด์ƒ ํ™•์ธํ•  ํ•„์š” ์—†์Œ
56+
}
57+
}
58+
}
59+
60+
// dp[s.length]๊ฐ€ true๋ผ๋ฉด ๋ฌธ์ž์—ด s๋ฅผ wordDict์˜ ๋‹จ์–ด๋“ค๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์Œ
61+
return dp[s.length];
62+
}
63+
64+
const s1 = "leetcode";
65+
const wordDict1 = ["leet", "code"];
66+
console.log(wordBreak(s1, wordDict1)); // true
67+
68+
const s2 = "applepenapple";
69+
const wordDict2 = ["apple", "pen"];
70+
console.log(wordBreak(s2, wordDict2)); // true
71+
72+
const s3 = "catsandog";
73+
const wordDict3 = ["cats", "dog", "sand", "and", "cat"];
74+
console.log(wordBreak(s3, wordDict3)); // false

0 commit comments

Comments
ย (0)