From faa08e2bd410627668769e83c51bb482302db90d Mon Sep 17 00:00:00 2001 From: Antim Pal <134076504+iamAntimPal@users.noreply.github.com> Date: Tue, 15 Apr 2025 07:05:17 +0530 Subject: [PATCH 1/5] Create 208. Implement Trie (Prefix Tree).py Co-Authored-By: Antim-IWP <203163676+Antim-IWP@users.noreply.github.com> Co-Authored-By: Shiwangi Srivastava <174641070+IamShiwangi@users.noreply.github.com> --- .../208. Implement Trie (Prefix Tree).py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Solution/208. Implement Trie (Prefix Tree)/208. Implement Trie (Prefix Tree).py diff --git a/Solution/208. Implement Trie (Prefix Tree)/208. Implement Trie (Prefix Tree).py b/Solution/208. Implement Trie (Prefix Tree)/208. Implement Trie (Prefix Tree).py new file mode 100644 index 0000000..e69de29 From 147684bd514176a4c9ff0ecc21640efbbc3a47ed Mon Sep 17 00:00:00 2001 From: Antim Pal <134076504+iamAntimPal@users.noreply.github.com> Date: Tue, 15 Apr 2025 07:05:25 +0530 Subject: [PATCH 2/5] Update 208. Implement Trie (Prefix Tree).py Co-Authored-By: Antim-IWP <203163676+Antim-IWP@users.noreply.github.com> Co-Authored-By: Shiwangi Srivastava <174641070+IamShiwangi@users.noreply.github.com> --- .../208. Implement Trie (Prefix Tree).py | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/Solution/208. Implement Trie (Prefix Tree)/208. Implement Trie (Prefix Tree).py b/Solution/208. Implement Trie (Prefix Tree)/208. Implement Trie (Prefix Tree).py index e69de29..286796c 100644 --- a/Solution/208. Implement Trie (Prefix Tree)/208. Implement Trie (Prefix Tree).py +++ b/Solution/208. Implement Trie (Prefix Tree)/208. Implement Trie (Prefix Tree).py @@ -0,0 +1,37 @@ +class Trie: + def __init__(self): + self.children = [None] * 26 + self.is_end = False + + def insert(self, word: str) -> None: + node = self + for c in word: + idx = ord(c) - ord('a') + if node.children[idx] is None: + node.children[idx] = Trie() + node = node.children[idx] + node.is_end = True + + def search(self, word: str) -> bool: + node = self._search_prefix(word) + return node is not None and node.is_end + + def startsWith(self, prefix: str) -> bool: + node = self._search_prefix(prefix) + return node is not None + + def _search_prefix(self, prefix: str): + node = self + for c in prefix: + idx = ord(c) - ord('a') + if node.children[idx] is None: + return None + node = node.children[idx] + return node + + +# Your Trie object will be instantiated and called as such: +# obj = Trie() +# obj.insert(word) +# param_2 = obj.search(word) +# param_3 = obj.startsWith(prefix) \ No newline at end of file From d4e554d8a937ff71088be89b9ab3e3981ac4fb45 Mon Sep 17 00:00:00 2001 From: Antim Pal <134076504+iamAntimPal@users.noreply.github.com> Date: Tue, 15 Apr 2025 07:05:45 +0530 Subject: [PATCH 3/5] Create readme.md Co-Authored-By: Antim-IWP <203163676+Antim-IWP@users.noreply.github.com> Co-Authored-By: Shiwangi Srivastava <174641070+IamShiwangi@users.noreply.github.com> --- Solution/208. Implement Trie (Prefix Tree)/readme.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Solution/208. Implement Trie (Prefix Tree)/readme.md diff --git a/Solution/208. Implement Trie (Prefix Tree)/readme.md b/Solution/208. Implement Trie (Prefix Tree)/readme.md new file mode 100644 index 0000000..e69de29 From 603bd68356284767ba6e5122670658344886ae83 Mon Sep 17 00:00:00 2001 From: Antim Pal <134076504+iamAntimPal@users.noreply.github.com> Date: Tue, 15 Apr 2025 07:05:50 +0530 Subject: [PATCH 4/5] Update readme.md Co-Authored-By: Antim-IWP <203163676+Antim-IWP@users.noreply.github.com> Co-Authored-By: Shiwangi Srivastava <174641070+IamShiwangi@users.noreply.github.com> --- .../readme.md | 549 ++++++++++++++++++ 1 file changed, 549 insertions(+) diff --git a/Solution/208. Implement Trie (Prefix Tree)/readme.md b/Solution/208. Implement Trie (Prefix Tree)/readme.md index e69de29..fe82e7b 100644 --- a/Solution/208. Implement Trie (Prefix Tree)/readme.md +++ b/Solution/208. Implement Trie (Prefix Tree)/readme.md @@ -0,0 +1,549 @@ +--- +comments: true +difficulty: Medium +edit_url: https://github.com/doocs/leetcode/edit/main/solution/0200-0299/0208.Implement%20Trie%20%28Prefix%20Tree%29/README_EN.md +tags: + - Design + - Trie + - Hash Table + - String +--- + + + +# [208. Implement Trie (Prefix Tree)](https://leetcode.com/problems/implement-trie-prefix-tree) + +[中文文档](/solution/0200-0299/0208.Implement%20Trie%20%28Prefix%20Tree%29/README.md) + +## Description + + + +

A trie (pronounced as "try") or prefix tree is a tree data structure used to efficiently store and retrieve keys in a dataset of strings. There are various applications of this data structure, such as autocomplete and spellchecker.

+ +

Implement the Trie class:

+ + + +

 

+

Example 1:

+ +
+Input
+["Trie", "insert", "search", "search", "startsWith", "insert", "search"]
+[[], ["apple"], ["apple"], ["app"], ["app"], ["app"], ["app"]]
+Output
+[null, null, true, false, true, null, true]
+
+Explanation
+Trie trie = new Trie();
+trie.insert("apple");
+trie.search("apple");   // return True
+trie.search("app");     // return False
+trie.startsWith("app"); // return True
+trie.insert("app");
+trie.search("app");     // return True
+
+ +

 

+

Constraints:

+ + + + + +## Solutions + + + +### Solution 1 + + + +#### Python3 + +```python +class Trie: + def __init__(self): + self.children = [None] * 26 + self.is_end = False + + def insert(self, word: str) -> None: + node = self + for c in word: + idx = ord(c) - ord('a') + if node.children[idx] is None: + node.children[idx] = Trie() + node = node.children[idx] + node.is_end = True + + def search(self, word: str) -> bool: + node = self._search_prefix(word) + return node is not None and node.is_end + + def startsWith(self, prefix: str) -> bool: + node = self._search_prefix(prefix) + return node is not None + + def _search_prefix(self, prefix: str): + node = self + for c in prefix: + idx = ord(c) - ord('a') + if node.children[idx] is None: + return None + node = node.children[idx] + return node + + +# Your Trie object will be instantiated and called as such: +# obj = Trie() +# obj.insert(word) +# param_2 = obj.search(word) +# param_3 = obj.startsWith(prefix) +``` + +#### Java + +```java +class Trie { + private Trie[] children; + private boolean isEnd; + + public Trie() { + children = new Trie[26]; + } + + public void insert(String word) { + Trie node = this; + for (char c : word.toCharArray()) { + int idx = c - 'a'; + if (node.children[idx] == null) { + node.children[idx] = new Trie(); + } + node = node.children[idx]; + } + node.isEnd = true; + } + + public boolean search(String word) { + Trie node = searchPrefix(word); + return node != null && node.isEnd; + } + + public boolean startsWith(String prefix) { + Trie node = searchPrefix(prefix); + return node != null; + } + + private Trie searchPrefix(String s) { + Trie node = this; + for (char c : s.toCharArray()) { + int idx = c - 'a'; + if (node.children[idx] == null) { + return null; + } + node = node.children[idx]; + } + return node; + } +} + +/** + * Your Trie object will be instantiated and called as such: + * Trie obj = new Trie(); + * obj.insert(word); + * boolean param_2 = obj.search(word); + * boolean param_3 = obj.startsWith(prefix); + */ +``` + +#### C++ + +```cpp +class Trie { +private: + vector children; + bool isEnd; + + Trie* searchPrefix(string s) { + Trie* node = this; + for (char c : s) { + int idx = c - 'a'; + if (!node->children[idx]) return nullptr; + node = node->children[idx]; + } + return node; + } + +public: + Trie() + : children(26) + , isEnd(false) {} + + void insert(string word) { + Trie* node = this; + for (char c : word) { + int idx = c - 'a'; + if (!node->children[idx]) node->children[idx] = new Trie(); + node = node->children[idx]; + } + node->isEnd = true; + } + + bool search(string word) { + Trie* node = searchPrefix(word); + return node != nullptr && node->isEnd; + } + + bool startsWith(string prefix) { + Trie* node = searchPrefix(prefix); + return node != nullptr; + } +}; + +/** + * Your Trie object will be instantiated and called as such: + * Trie* obj = new Trie(); + * obj->insert(word); + * bool param_2 = obj->search(word); + * bool param_3 = obj->startsWith(prefix); + */ +``` + +#### Go + +```go +type Trie struct { + children [26]*Trie + isEnd bool +} + +func Constructor() Trie { + return Trie{} +} + +func (this *Trie) Insert(word string) { + node := this + for _, c := range word { + idx := c - 'a' + if node.children[idx] == nil { + node.children[idx] = &Trie{} + } + node = node.children[idx] + } + node.isEnd = true +} + +func (this *Trie) Search(word string) bool { + node := this.SearchPrefix(word) + return node != nil && node.isEnd +} + +func (this *Trie) StartsWith(prefix string) bool { + node := this.SearchPrefix(prefix) + return node != nil +} + +func (this *Trie) SearchPrefix(s string) *Trie { + node := this + for _, c := range s { + idx := c - 'a' + if node.children[idx] == nil { + return nil + } + node = node.children[idx] + } + return node +} + +/** + * Your Trie object will be instantiated and called as such: + * obj := Constructor(); + * obj.Insert(word); + * param_2 := obj.Search(word); + * param_3 := obj.StartsWith(prefix); + */ +``` + +#### TypeScript + +```ts +class TrieNode { + children; + isEnd; + constructor() { + this.children = new Array(26); + this.isEnd = false; + } +} + +class Trie { + root; + constructor() { + this.root = new TrieNode(); + } + + insert(word: string): void { + let head = this.root; + for (let char of word) { + let index = char.charCodeAt(0) - 97; + if (!head.children[index]) { + head.children[index] = new TrieNode(); + } + head = head.children[index]; + } + head.isEnd = true; + } + + search(word: string): boolean { + let head = this.searchPrefix(word); + return head != null && head.isEnd; + } + + startsWith(prefix: string): boolean { + return this.searchPrefix(prefix) != null; + } + + private searchPrefix(prefix: string) { + let head = this.root; + for (let char of prefix) { + let index = char.charCodeAt(0) - 97; + if (!head.children[index]) return null; + head = head.children[index]; + } + return head; + } +} +``` + +#### Rust + +```rust +use std::{cell::RefCell, collections::HashMap, rc::Rc}; + +struct TrieNode { + pub val: Option, + pub flag: bool, + pub child: HashMap>>, +} + +impl TrieNode { + fn new() -> Self { + Self { + val: None, + flag: false, + child: HashMap::new(), + } + } + + fn new_with_val(val: char) -> Self { + Self { + val: Some(val), + flag: false, + child: HashMap::new(), + } + } +} + +struct Trie { + root: Rc>, +} + +/// Your Trie object will be instantiated and called as such: +/// let obj = Trie::new(); +/// obj.insert(word); +/// let ret_2: bool = obj.search(word); +/// let ret_3: bool = obj.starts_with(prefix); +impl Trie { + fn new() -> Self { + Self { + root: Rc::new(RefCell::new(TrieNode::new())), + } + } + + fn insert(&self, word: String) { + let char_vec: Vec = word.chars().collect(); + // Get the clone of current root node + let mut root = Rc::clone(&self.root); + for c in &char_vec { + if !root.borrow().child.contains_key(c) { + // We need to manually create the entry + root.borrow_mut() + .child + .insert(*c, Rc::new(RefCell::new(TrieNode::new()))); + } + // Get the child node + let root_clone = Rc::clone(root.borrow().child.get(c).unwrap()); + root = root_clone; + } + { + root.borrow_mut().flag = true; + } + } + + fn search(&self, word: String) -> bool { + let char_vec: Vec = word.chars().collect(); + // Get the clone of current root node + let mut root = Rc::clone(&self.root); + for c in &char_vec { + if !root.borrow().child.contains_key(c) { + return false; + } + // Get the child node + let root_clone = Rc::clone(root.borrow().child.get(c).unwrap()); + root = root_clone; + } + let flag = root.borrow().flag; + flag + } + + fn starts_with(&self, prefix: String) -> bool { + let char_vec: Vec = prefix.chars().collect(); + // Get the clone of current root node + let mut root = Rc::clone(&self.root); + for c in &char_vec { + if !root.borrow().child.contains_key(c) { + return false; + } + // Get the child node + let root_clone = Rc::clone(root.borrow().child.get(c).unwrap()); + root = root_clone; + } + true + } +} +``` + +#### JavaScript + +```js +/** + * Initialize your data structure here. + */ +var Trie = function () { + this.children = {}; +}; + +/** + * Inserts a word into the trie. + * @param {string} word + * @return {void} + */ +Trie.prototype.insert = function (word) { + let node = this.children; + for (let char of word) { + if (!node[char]) { + node[char] = {}; + } + node = node[char]; + } + node.isEnd = true; +}; + +/** + * Returns if the word is in the trie. + * @param {string} word + * @return {boolean} + */ +Trie.prototype.search = function (word) { + let node = this.searchPrefix(word); + return node != undefined && node.isEnd != undefined; +}; + +Trie.prototype.searchPrefix = function (prefix) { + let node = this.children; + for (let char of prefix) { + if (!node[char]) return false; + node = node[char]; + } + return node; +}; + +/** + * Returns if there is any word in the trie that starts with the given prefix. + * @param {string} prefix + * @return {boolean} + */ +Trie.prototype.startsWith = function (prefix) { + return this.searchPrefix(prefix); +}; + +/** + * Your Trie object will be instantiated and called as such: + * var obj = new Trie() + * obj.insert(word) + * var param_2 = obj.search(word) + * var param_3 = obj.startsWith(prefix) + */ +``` + +#### C# + +```cs +public class Trie { + bool isEnd; + Trie[] children = new Trie[26]; + + public Trie() { + + } + + public void Insert(string word) { + Trie node = this; + foreach (var c in word) + { + var idx = c - 'a'; + node.children[idx] ??= new Trie(); + node = node.children[idx]; + } + node.isEnd = true; + } + + public bool Search(string word) { + Trie node = SearchPrefix(word); + return node != null && node.isEnd; + } + + public bool StartsWith(string prefix) { + Trie node = SearchPrefix(prefix); + return node != null; + } + + private Trie SearchPrefix(string s) { + Trie node = this; + foreach (var c in s) + { + var idx = c - 'a'; + if (node.children[idx] == null) + { + return null; + } + node = node.children[idx]; + } + return node; + } +} + +/** + * Your Trie object will be instantiated and called as such: + * Trie obj = new Trie(); + * obj.Insert(word); + * bool param_2 = obj.Search(word); + * bool param_3 = obj.StartsWith(prefix); + */ +``` + + + + + + \ No newline at end of file From d1ee7417e5cb00509385e7db60b0a700cccda667 Mon Sep 17 00:00:00 2001 From: Antim Pal <134076504+iamAntimPal@users.noreply.github.com> Date: Tue, 15 Apr 2025 07:06:46 +0530 Subject: [PATCH 5/5] Update readme.md Co-Authored-By: Antim-IWP <203163676+Antim-IWP@users.noreply.github.com> Co-Authored-By: Shiwangi Srivastava <174641070+IamShiwangi@users.noreply.github.com> --- .../readme.md | 326 +----------------- 1 file changed, 1 insertion(+), 325 deletions(-) diff --git a/Solution/208. Implement Trie (Prefix Tree)/readme.md b/Solution/208. Implement Trie (Prefix Tree)/readme.md index fe82e7b..399d79b 100644 --- a/Solution/208. Implement Trie (Prefix Tree)/readme.md +++ b/Solution/208. Implement Trie (Prefix Tree)/readme.md @@ -1,7 +1,7 @@ --- comments: true difficulty: Medium -edit_url: https://github.com/doocs/leetcode/edit/main/solution/0200-0299/0208.Implement%20Trie%20%28Prefix%20Tree%29/README_EN.md +edit_url: Antim tags: - Design - Trie @@ -13,7 +13,6 @@ tags: # [208. Implement Trie (Prefix Tree)](https://leetcode.com/problems/implement-trie-prefix-tree) -[中文文档](/solution/0200-0299/0208.Implement%20Trie%20%28Prefix%20Tree%29/README.md) ## Description @@ -219,329 +218,6 @@ public: */ ``` -#### Go - -```go -type Trie struct { - children [26]*Trie - isEnd bool -} - -func Constructor() Trie { - return Trie{} -} - -func (this *Trie) Insert(word string) { - node := this - for _, c := range word { - idx := c - 'a' - if node.children[idx] == nil { - node.children[idx] = &Trie{} - } - node = node.children[idx] - } - node.isEnd = true -} - -func (this *Trie) Search(word string) bool { - node := this.SearchPrefix(word) - return node != nil && node.isEnd -} - -func (this *Trie) StartsWith(prefix string) bool { - node := this.SearchPrefix(prefix) - return node != nil -} - -func (this *Trie) SearchPrefix(s string) *Trie { - node := this - for _, c := range s { - idx := c - 'a' - if node.children[idx] == nil { - return nil - } - node = node.children[idx] - } - return node -} - -/** - * Your Trie object will be instantiated and called as such: - * obj := Constructor(); - * obj.Insert(word); - * param_2 := obj.Search(word); - * param_3 := obj.StartsWith(prefix); - */ -``` - -#### TypeScript - -```ts -class TrieNode { - children; - isEnd; - constructor() { - this.children = new Array(26); - this.isEnd = false; - } -} - -class Trie { - root; - constructor() { - this.root = new TrieNode(); - } - - insert(word: string): void { - let head = this.root; - for (let char of word) { - let index = char.charCodeAt(0) - 97; - if (!head.children[index]) { - head.children[index] = new TrieNode(); - } - head = head.children[index]; - } - head.isEnd = true; - } - - search(word: string): boolean { - let head = this.searchPrefix(word); - return head != null && head.isEnd; - } - - startsWith(prefix: string): boolean { - return this.searchPrefix(prefix) != null; - } - - private searchPrefix(prefix: string) { - let head = this.root; - for (let char of prefix) { - let index = char.charCodeAt(0) - 97; - if (!head.children[index]) return null; - head = head.children[index]; - } - return head; - } -} -``` - -#### Rust - -```rust -use std::{cell::RefCell, collections::HashMap, rc::Rc}; - -struct TrieNode { - pub val: Option, - pub flag: bool, - pub child: HashMap>>, -} - -impl TrieNode { - fn new() -> Self { - Self { - val: None, - flag: false, - child: HashMap::new(), - } - } - - fn new_with_val(val: char) -> Self { - Self { - val: Some(val), - flag: false, - child: HashMap::new(), - } - } -} - -struct Trie { - root: Rc>, -} - -/// Your Trie object will be instantiated and called as such: -/// let obj = Trie::new(); -/// obj.insert(word); -/// let ret_2: bool = obj.search(word); -/// let ret_3: bool = obj.starts_with(prefix); -impl Trie { - fn new() -> Self { - Self { - root: Rc::new(RefCell::new(TrieNode::new())), - } - } - - fn insert(&self, word: String) { - let char_vec: Vec = word.chars().collect(); - // Get the clone of current root node - let mut root = Rc::clone(&self.root); - for c in &char_vec { - if !root.borrow().child.contains_key(c) { - // We need to manually create the entry - root.borrow_mut() - .child - .insert(*c, Rc::new(RefCell::new(TrieNode::new()))); - } - // Get the child node - let root_clone = Rc::clone(root.borrow().child.get(c).unwrap()); - root = root_clone; - } - { - root.borrow_mut().flag = true; - } - } - - fn search(&self, word: String) -> bool { - let char_vec: Vec = word.chars().collect(); - // Get the clone of current root node - let mut root = Rc::clone(&self.root); - for c in &char_vec { - if !root.borrow().child.contains_key(c) { - return false; - } - // Get the child node - let root_clone = Rc::clone(root.borrow().child.get(c).unwrap()); - root = root_clone; - } - let flag = root.borrow().flag; - flag - } - - fn starts_with(&self, prefix: String) -> bool { - let char_vec: Vec = prefix.chars().collect(); - // Get the clone of current root node - let mut root = Rc::clone(&self.root); - for c in &char_vec { - if !root.borrow().child.contains_key(c) { - return false; - } - // Get the child node - let root_clone = Rc::clone(root.borrow().child.get(c).unwrap()); - root = root_clone; - } - true - } -} -``` - -#### JavaScript - -```js -/** - * Initialize your data structure here. - */ -var Trie = function () { - this.children = {}; -}; - -/** - * Inserts a word into the trie. - * @param {string} word - * @return {void} - */ -Trie.prototype.insert = function (word) { - let node = this.children; - for (let char of word) { - if (!node[char]) { - node[char] = {}; - } - node = node[char]; - } - node.isEnd = true; -}; - -/** - * Returns if the word is in the trie. - * @param {string} word - * @return {boolean} - */ -Trie.prototype.search = function (word) { - let node = this.searchPrefix(word); - return node != undefined && node.isEnd != undefined; -}; - -Trie.prototype.searchPrefix = function (prefix) { - let node = this.children; - for (let char of prefix) { - if (!node[char]) return false; - node = node[char]; - } - return node; -}; - -/** - * Returns if there is any word in the trie that starts with the given prefix. - * @param {string} prefix - * @return {boolean} - */ -Trie.prototype.startsWith = function (prefix) { - return this.searchPrefix(prefix); -}; - -/** - * Your Trie object will be instantiated and called as such: - * var obj = new Trie() - * obj.insert(word) - * var param_2 = obj.search(word) - * var param_3 = obj.startsWith(prefix) - */ -``` - -#### C# - -```cs -public class Trie { - bool isEnd; - Trie[] children = new Trie[26]; - - public Trie() { - - } - - public void Insert(string word) { - Trie node = this; - foreach (var c in word) - { - var idx = c - 'a'; - node.children[idx] ??= new Trie(); - node = node.children[idx]; - } - node.isEnd = true; - } - - public bool Search(string word) { - Trie node = SearchPrefix(word); - return node != null && node.isEnd; - } - - public bool StartsWith(string prefix) { - Trie node = SearchPrefix(prefix); - return node != null; - } - - private Trie SearchPrefix(string s) { - Trie node = this; - foreach (var c in s) - { - var idx = c - 'a'; - if (node.children[idx] == null) - { - return null; - } - node = node.children[idx]; - } - return node; - } -} - -/** - * Your Trie object will be instantiated and called as such: - * Trie obj = new Trie(); - * obj.Insert(word); - * bool param_2 = obj.Search(word); - * bool param_3 = obj.StartsWith(prefix); - */ -``` -