Skip to content

Commit

Permalink
Implement Trie (Prefix Tree)
Browse files Browse the repository at this point in the history
  • Loading branch information
lledellebell committed Jan 6, 2025
1 parent 5a677bd commit 1a8ba73
Showing 1 changed file with 115 additions and 0 deletions.
115 changes: 115 additions & 0 deletions implement-trie-prefix-tree/lledellebell.js
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 1a8ba73

Please sign in to comment.