1. 程式人生 > >LeetCode 208. Implement Trie (Prefix Tree)

LeetCode 208. Implement Trie (Prefix Tree)

== this thum 單詞查找 cheng node 順序 and code

Implement a trie with insert, search, and startsWith methods.

Note:
You may assume that all inputs are consist of lowercase letters a-z.

這道題讓我們實現一個重要但又有些復雜的數據結構-字典樹, 又稱前綴樹或單詞查找樹,詳細介紹可以參見網友董的博客,例如,一個保存了8個鍵的trie結構,"A", "to", "tea", "ted", "ten", "i", "in", and "inn".如下圖所示:

技術分享

字典樹主要有如下三點性質:

1. 根節點不包含字符,除根節點意外每個節點只包含一個字符。

2. 從根節點到某一個節點,路徑上經過的字符連接起來,為該節點對應的字符串。

3. 每個節點的所有子節點包含的字符串不相同。

字母樹的插入(Insert)、刪除( Delete)和查找(Find)都非常簡單,用一個一重循環即可,即第i 次循環找到前i 個字母所對應的子樹,然後進行相應的操作。實現這棵字母樹,我們用最常見的數組保存(靜態開辟內存)即可,當然也可以開動態的指針類型(動態開辟內存)。至於結點對兒子的指向,一般有三種方法:

1、對每個結點開一個字母集大小的數組,對應的下標是兒子所表示的字母,內容則是這個兒子對應在大數組上的位置,即標號;

2、對每個結點掛一個鏈表,按一定順序記錄每個兒子是誰;

3、使用左兒子右兄弟表示法記錄這棵樹。

兩種方法,各有特點。第一種易實現,但實際的空間要求較大;第二種,空間要求最小,但相對費時且不易寫。

1.我們先來看第一種實現方法,這種方法實現起來簡單直觀,字母的字典樹每個節點要定義一個大小為26的子節點指針數組,然後用一個標誌符用來記錄到當前位置為止是否為一個詞,初始化的時候講26個子節點都賦為空。那麽insert操作只需要對於要插入的字符串的每一個字符算出其的位置,然後找是否存在這個子節點,若不存在則新建一個,然後再查找下一個。查找詞和找前綴操作跟insert操作都很類似,不同點在於若不存在子節點,則返回false。查找次最後還要看標識位,而找前綴直接返回true即可

 1 class TrieNode {
 2     public char val;
 3     public boolean isWord; 
 4     public TrieNode[] children = new TrieNode[26];
 5     public TrieNode() {}
 6     TrieNode(char c){
 7         TrieNode node = new TrieNode();
 8         node.val = c;
 9     }
10 }
11 
12 public class Trie {
13     private TrieNode root;
14     public Trie() {
15         root = new TrieNode();
16         root.val = ‘ ‘;
17     }
18 
19     public void insert(String word) {
20         TrieNode ws = root;
21         for(int i = 0; i < word.length(); i++){
22             char c = word.charAt(i);
23             if(ws.children[c - ‘a‘] == null){
24                 ws.children[c - ‘a‘] = new TrieNode(c);
25             }
26             ws = ws.children[c - ‘a‘];
27         }
28         ws.isWord = true;
29     }
30 
31     public boolean search(String word) {
32         TrieNode ws = root; 
33         for(int i = 0; i < word.length(); i++){
34             char c = word.charAt(i);
35             if(ws.children[c - ‘a‘] == null) return false;
36             ws = ws.children[c - ‘a‘];
37         }
38         return ws.isWord;
39     }
40 
41     public boolean startsWith(String prefix) {
42         TrieNode ws = root; 
43         for(int i = 0; i < prefix.length(); i++){
44             char c = prefix.charAt(i);
45             if(ws.children[c - ‘a‘] == null) return false;
46             ws = ws.children[c - ‘a‘];
47         }
48         return true;
49     }
50 }

2.

  1 class Trie {
  2     private String letter;
  3     private List<Trie> children;
  4     private boolean end;
  5     /** Initialize your data structure here. */
  6     public Trie() {
  7         this.letter = "";
  8         this.children = new ArrayList<Trie>();
  9         boolean end = false;
 10     }
 11     
 12     public Trie(String letter) {
 13         this.letter = letter;
 14         this.children = new ArrayList<Trie>();
 15         this.end = false;
 16     }
 17     
 18     /** Inserts a word into the trie. */
 19     public void insert(String word) {
 20         insertHelper(this, word, 0);
 21     }
 22     
 23     /** Returns if the word is in the trie. */
 24     public boolean search(String word) {
 25         boolean result = true;
 26         result = result && searchHelper(this, word, 0);
 27         return result;
 28     }
 29     
 30     /** Returns if there is any word in the trie that starts with the given prefix. */
 31     public boolean startsWith(String prefix) {
 32         if (prefix.length() == 0)
 33             return true;
 34         boolean result = false;
 35         for(Trie trie: children){
 36             if (trie.letter.equals(prefix.charAt(0) + "")){
 37                 result = true && startsWithHelper(trie, prefix, 1);
 38                 if(result == false)
 39                     return false;
 40             }
 41         }
 42         return result;
 43     }
 44     
 45     private boolean startsWithHelper(Trie trie, String prefix, int pos){
 46         if(pos == prefix.length())
 47             return true;
 48         boolean result = false;
 49         for(Trie child: trie.children){
 50             if(child.letter.equals(prefix.charAt(pos) + "")){
 51                 result = true && startsWithHelper(child, prefix, pos +1);
 52                 if(result == false)
 53                     return false;
 54             }   
 55         }
 56         return result;
 57     }
 58     
 59     private void insertHelper(Trie trie, String word, int pos){
 60         boolean has = false;
 61         if(pos == word.length())
 62             return;
 63         int len = trie.children.size();
 64         for(int i=0; i < len; i++){
 65             Trie child = trie.children.get(i);
 66             if(child.letter.equals(word.charAt(pos) + "")){
 67                 has = true;
 68                 if(pos == word.length()-1){
 69                     if(child.end == false){
 70                         child.end = true;
 71                     }
 72                 }
 73                 insertHelper(child, word, pos+1);
 74             }
 75         }
 76         if(!has)
 77             create(trie,word,pos);
 78     }
 79     
 80     private void create(Trie parent, String word, int pos){
 81         if(pos == word.length())
 82             return;
 83         Trie child = new Trie(word.charAt(pos) + "");
 84         if(pos == word.length() -1)
 85             child.end = true;
 86         parent.children.add(child);
 87         create(child, word, pos+1);
 88     }
 89     
 90     private boolean searchHelper(Trie trie, String word, int pos){
 91         if(pos == word.length() && trie.children.size() == 0)
 92             return true;
 93         else if(pos == word.length())
 94             return false;
 95         boolean result = false;
 96         for(Trie child: trie.children){
 97             if(child.letter.equals(word.charAt(pos) + "")){
 98                 if(pos == word.length() -1){
 99                     if(child.end == true)
100                         return true;
101                     else
102                         return false;
103                 }
104                 result = true && searchHelper(child, word, pos +1);
105                 if(result == false)
106                     return false;
107             }
109         }
110         return result;
111     }
112 }

LeetCode 208. Implement Trie (Prefix Tree)