實現 Trie (字首樹)
阿新 • • 發佈:2020-11-06
題目:
實現一個 Trie (字首樹),包含insert
,search
, 和startsWith
這三個操作。
Trie trie = new Trie(); trie.insert("apple"); trie.search("apple"); // 返回 true trie.search("app"); // 返回 false trie.startsWith("app"); // 返回 true trie.insert("app"); trie.search("app"); // 返回 true
思路:
Trie 樹的結點結構
Trie 樹是一個有根的樹,其結點具有以下欄位:
- 最多 R 個指向子結點的連結,其中每個連結對應字母表資料集中的一個字母。本文中假定 R 為 26,小寫拉丁字母的數量。
- 布林欄位,以指定節點是對應鍵的結尾還是隻是鍵字首。
Trie 樹中最常見的兩個操作是鍵的插入和查詢。
向 Trie 樹中插入鍵
我們通過搜尋 Trie 樹來插入一個鍵。我們從根開始搜尋它對應於第一個鍵字元的連結。有兩種情況:
- 連結存在。沿著連結移動到樹的下一個子層。演算法繼續搜尋下一個鍵字元。
- 連結不存在。建立一個新的節點,並將它與父節點的連結相連,該連結與當前的鍵字元相匹配。
重複以上步驟,直到到達鍵的最後一個字元,然後將當前節點標記為結束節點,演算法完成。
在 Trie 樹中查詢鍵
每個鍵在 trie 中表示為從根到內部節點或葉的路徑。我們用第一個鍵字元從根開始,。檢查當前節點中與鍵字元對應的連結。有兩種情況:
- 存在連結。我們移動到該連結後面路徑中的下一個節點,並繼續搜尋下一個鍵字元。
- 不存在連結。若已無鍵字元,且當前結點標記為 isEnd,則返回 true。否則有兩種可能,均返回 false :
- 還有鍵字元剩餘,但無法跟隨 Trie 樹的鍵路徑,找不到鍵。
- 沒有鍵字元剩餘,但當前結點沒有標記為 isEnd。也就是說,待查詢鍵只是Trie樹中另一個鍵的字首。
查詢 Trie 樹中的鍵字首
該方法和查詢基本相似,甚至更簡單因為不需要考慮當前 Trie 節點是否用 “isend” 標記,因為我們搜尋的是鍵的字首,而不是整個鍵。
程式碼
package main import "fmt" type Trie struct { next [26]*Trie isEnd bool } /** Initialize your data structure here. */ func Constructor() *Trie { return &Trie{} } /** Inserts a word into the trie. */ func (this *Trie) Insert(word string) { for _, v := range word { if this.next[v-'a'] == nil { this.next[v-'a'] = new(Trie) this = this.next[v-'a'] }else { this = this.next[v-'a'] } } this.isEnd = true } /** Returns if the word is in the trie. */ func (this *Trie) Search(word string) bool { for _, v := range word { if this.next[v-'a'] == nil { return false } this = this.next[v-'a'] } if this.isEnd == false { return false } return true } /** Returns if there is any word in the trie that starts with the given prefix. */ func (this *Trie) StartsWith(prefix string) bool { for _, v := range prefix { if this.next[v-'a'] == nil { return false } this = this.next[v-'a'] } return true } func main() { trie := Constructor() trie.Insert("apple"); fmt.Println(trie.Search("apple")) // 返回 true fmt.Println(trie.Search("app")) // 返回 false fmt.Println(trie.StartsWith("app")) // 返回 true trie.Insert("app") fmt.Println(trie.Search("app")) // 返回 true }
地址:https://mp.weixin.qq.com/s/qkM88Ok-SY-QjoI-6hVCOw