<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          每日一題 | Python3 實現(xiàn)「208. 實現(xiàn) Trie(前綴樹)」

          共 6177字,需瀏覽 13分鐘

           ·

          2021-04-14 20:37

          208. 實現(xiàn) Trie (前綴樹)

          題目鏈接

          https://leetcode-cn.com/problems/implement-trie-prefix-tree/

          也可以點擊「閱讀原文」直達題目鏈接。

          題目描述

          Trie(發(fā)音類似 "try")或者說 前綴樹 是一種樹形數(shù)據(jù)結(jié)構(gòu),用于高效地存儲和檢索字符串數(shù)據(jù)集中的鍵。這一數(shù)據(jù)結(jié)構(gòu)有相當多的應用情景,例如自動補完和拼寫檢查。

          請你實現(xiàn) Trie 類:

          • Trie() 初始化前綴樹對象。
          • void insert(String word) 向前綴樹中插入字符串 word
          • boolean search(String word) 如果字符串 word 在前綴樹中,返回 true(即,在檢索之前已經(jīng)插入);否則,返回 false
          • boolean startsWith(String prefix) 如果之前已經(jīng)插入的字符串 word 的前綴之一為 prefix ,返回 true ;否則,返回 false

          示例 :

          輸入
          ["Trie""insert""search""search""startsWith""insert""search"]
          [[], ["apple"], ["apple"], ["app"], ["app"], ["app"], ["app"]]

          輸出
          [null, null, truefalsetrue, null, true]

          解釋
          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

          提示:

          • 1 <= word.length, prefix.length <= 2000
          • wordprefix 僅由小寫英文字母組成
          • insert、searchstartsWith 調(diào)用次數(shù) 總計 不超過

          解題思路

          這道題考查的是前綴樹的思想。

          前綴樹在實際的工程應用中有著很大的應用。很常見的包括搜索引擎的關(guān)鍵詞提示功能,以及 IDE 的自動補全功能等等...

          Trie 樹的本質(zhì)是將重復的前綴子串進行合并的思想,也就是說如果一個字符出現(xiàn)了多次,但是只需要存儲一次就可以了。

          剛開始的時候,Trie 樹是一顆空樹,Trie 樹的構(gòu)造過程就是相當于往 Trie 樹中插入字符串,當字符串插入完畢后,Trie 樹就構(gòu)造完成了。

          這里我找了一個 Trie 構(gòu)造過程,你可以看下。假定要插入的字符串一共有 6 個,分別是"how", "hi", "her", "hello", "so", "see"。紅色節(jié)點表示一個字符串的結(jié)尾。

          "how"、"hi"、"her" 依次插入 Trie 樹
          "hello"、"so"、"see" 依次插入 Trie 樹

          那么應該如何實現(xiàn)呢?因為題目中我們假定字符串只包含小寫字母。因為小寫字母一共有 26 個,仿照二叉樹的存儲方式,我們可以使用一個大小為 26 的數(shù)組來存儲其孩子節(jié)點。另外,對于每一個節(jié)點,還需要一個額外的變量來記錄此節(jié)點代表的字符是否是一個字符串的結(jié)尾,為 True 的話代表著圖中的紅色節(jié)點。

          另外呢,因為數(shù)組有天然的支持下標索引的特性,因此我們甚至可以不存儲節(jié)點存儲的數(shù)據(jù),因為在進行查找的時候,直接通過字符 ASCII 碼的相對值作為訪問孩子數(shù)組的下標即可。

          Python3 代碼

          class Trie:

              def __init__(self):
                  """
                  Initialize your data structure here.
                  """

                  self._children = [None] * 26
                  self._is_ending_char = False


              def insert(self, word: str) -> None:
                  """
                  Inserts a word into the trie.
                  """

                  root = self
                  for index, char in map(lambda x: (ord(x) - ord("a"), x), word):
                      if not root._children[index]:
                          root._children[index] = Trie()
                      root = root._children[index]
                  root._is_ending_char = True


              def search(self, word: str) -> bool:
                  """
                  Returns if the word is in the trie.
                  """

                  root = self
                  for index in map(lambda x: ord(x) - ord("a"), word):
                      if not root._children[index]:
                          return False
                      root = root._children[index]
                  return root._is_ending_char


              def startsWith(self, prefix: str) -> bool:
                  """
                  Returns if there is any word in the trie that starts with the given prefix.
                  """

                  root = self
                  for index in map(lambda x: ord(x) - ord("a"), prefix):
                      if not root._children[index]:
                          return False
                      root = root._children[index]
                  return True


          # 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)

          復雜度分析:

          時間復雜度:

          空間復雜度:

          其中 n 為要插入字符串的總長度,k 為查詢字符串的長度。也就是說,Trie 樹構(gòu)造完成后,查詢的時間復雜度只和要查詢字符串的長度有關(guān),而構(gòu)造 Trie 樹,也就是插入的時候,時間復雜度是所有要插入的字符串的長度之和。

          總結(jié)

          雖然 Trie 樹的思想是合并重復的前綴子串,看上去節(jié)省了存儲空間,但實際上 Trie 樹利用的是空間換時間的思想,因為每個節(jié)點需要一個孩子數(shù)組,用于指向下一層的地址。在字符的范圍很大的時候,比如說不僅僅只有英文小寫字母的時候,光存儲 孩子數(shù)組就需要浪費很多的存儲空間。如果再考慮中文的話,所耗費的空間就更大了。

          因此,Trie 樹有很多可以優(yōu)化的地方,比如說縮點優(yōu)化,感興趣的可以自己下去搜索下。還有一個常見的方法就是孩子數(shù)組利用有序數(shù)組來進行實現(xiàn),不用事先申請全部字符所占的空間,遇到不存在的字符時,將其插入到其應該所在的位置即可。

          好了,今天的內(nèi)容就到這里了。我最近在學習數(shù)據(jù)結(jié)構(gòu)與算法的相關(guān)知識,也會在力扣進行每日一題的打卡。如果你最近在求職面試或者也在進行力扣進行每日一題的打卡的話,歡迎加入我們,后臺回復「加群」即可。我一直堅信一個人走的更快,一群人走的更遠。很多時候,只要堅持下去了,那么你就超越了很多人。

          參考資料:

          • https://time.geekbang.org/column/article/72414
          • https://leetcode-cn.com/problems/implement-trie-prefix-tree/solution/yu-ni-yi-qi-xue-suan-fa-python3-shi-xian-p0fr/

          瀏覽 47
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产一区二区大鸡巴操女女在线视频91 | 欧美性爱网站操 | 成人网站欧美 | 狠狠色7777 | 豆花视频www888 |