|
| 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 |
0 commit comments