1. 程式人生 > 其它 >1804. 實現 Trie (字首樹) II

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--;

        }
    }
}