1804. 實現 Trie (字首樹) II
字首樹(trie,發音為 "try")是一個樹狀的資料結構,用於高效地儲存和檢索一系列字串的字首。字首樹有許多應用,如自動補全和拼寫檢查。
實現字首樹 Trie 類:
Trie()初始化字首樹物件。
void insert(String word)將字串word插入字首樹中。
int countWordsEqualTo(String word)返回字首樹中字串word的例項個數。
int countWordsStartingWith(String prefix)返回字首樹中以prefix為字首的字串個數。
void erase(String word)從字首樹中移除字串word 。
示例 1:
Trie trie = new Trie();
trie.insert("apple"); // 插入 "apple"。
trie.insert("apple"); // 插入另一個 "apple"。
trie.countWordsEqualTo("apple"); // 有兩個 "apple" 例項,所以返回 2。
trie.countWordsStartingWith("app"); // "app" 是 "apple" 的字首,所以返回 2。
trie.erase("apple"); // 移除一個 "apple"。
trie.countWordsEqualTo("apple"); // 現在只有一個 "apple" 例項,所以返回 1。
trie.countWordsStartingWith("app"); // 返回 1
trie.erase("apple"); // 移除 "apple"。現在字首樹是空的。
trie.countWordsStartingWith("app"); // 返回 0
public class TrieTree { public static class TrieNode{ public int pass; public int end; // public HashMap<Character,TrieNode> map=new HashMap<>(); //a->0,b->1,z->25 public TrieNode[] nexts=new TrieNode[26]; } public static class Trie{ private TrieNode root; public Trie(){ root=new TrieNode(); } /** 遍歷所有字元,如果該字元沒有路了,則建出node,pass++ 到最後一個字元時end++ 時間複雜度是:所有字元的數量 */ public void insert(String word){ if(word==null){ return; } char[] chs=word.toCharArray(); TrieNode node=root; node.pass++; int index; for(int i=0;i<chs.length;i++){ index=chs[i]-'a'; if(node.nexts[index]==null){ node.nexts[index]=new TrieNode(); } node=node.nexts[index]; node.pass++; } node.end++; } /** 查word加入了幾次 O(K) 這個hashmap也可以 */ public int search(String word){ if(word==null){ return 0; } char[] chs=word.toCharArray(); TrieNode node=root; int index=0; for(int i=0;i<chs.length;i++){ index=chs[i]-'a'; if(node.nexts[index]==null){//說明沒有路了,則表示沒有加入過 return 0; } //否則繼續走 node=node.nexts[index]; } return node.end; } /** 有多少個字串以word為字首的,這個hashMap做不到 時間複雜度:O(K) 沿途找,返回最後一個字元node的pass */ public int preNumber(String word){ if(word==null){ return 0; } char[] chs=word.toCharArray(); TrieNode node=root; int index=0; for(int i=0;i<chs.length;i++){ index=chs[i]-'a'; if(node.nexts[index]==null){//沒有路了,說明沒有這個字首 return 0; } node=node.nexts[index]; } return node.pass; } /** 先保證加入過才能刪除 沿途pass-- 最後end-- 注意:如果pass減為0時該怎麼辦? 把這條路徑標為null,jvm會自動回收這個node */ public void delete(String word){ if(search(word)==0){ return; } char[] chs=word.toCharArray(); TrieNode node=root; node.pass--; int index=0; for(int i=0;i<chs.length;i++){ index=chs[i]-'a'; if(--node.nexts[index].pass==0){ //如果pass=0則 node.nexts[index]=null; return; } node=node.nexts[index]; } node.end--; } } }