Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
lledellebell committed Jan 7, 2025
2 parents cfb2c82 + 1d57393 commit 6f7243a
Show file tree
Hide file tree
Showing 2 changed files with 189 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
74 changes: 74 additions & 0 deletions word-break/lledellebell.js
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 6f7243a

Please sign in to comment.