1. 程式人生 > >LeetCode Medium 211 新增與查詢單詞 Python

LeetCode Medium 211 新增與查詢單詞 Python

"""
    演算法:利用Trie樹
    思路:
        存這種字串型別的資料,Trie樹是一個比較適當的資料結構,所以聯想208題建立Trie樹的過程,可以比較
        輕鬆地選定資料結構,並且寫好addWord
        難點和關鍵在於search這裡,主要是search中的'.'該如何處理

            其實比較容易想到的思路就是用dfs,結合208題正常Trie樹的search,在正常的Trie樹中搜索字串的
        時候,對某個字元char,向下只會走一條道路,或者無路可走,可以比較直觀地找到路徑,這裡有萬用字元'.'後,
        就是要向下走所有可能的子節點,b.d,在某個node處,node的children={'a':x1,'c':x2,'e':x3},則
        b.d可以向下可以有x1,x2,x3三個子節點可以走,而一個特定的單詞如bad,就只能走x1,相當於一個不含
        '.'的位置,向下走的選擇只有1個或者0個,而含'.'的位置,向下可以走所有
            [next_node  for next_node in node.chilren.values()]
            所以自然地選擇用dfs來做,這裡dfs的難點在於終止位置、條件,以及如何恰當地構造出遞迴的關係
            首先是程式引數, 一種比較自然的想法就是每次在乎當前要判斷的字元以及當前所在節點,所以考慮root,i
        先不管程式出口(二叉樹中root == None ,return None 這種)
            先區分word[i] 是否為'.' ,是的話,遞迴遍歷所有可能子節點,否則的話,只有當word[i] in node.children,
        才遞迴。
            如何向下遞迴?
                首先要明確這裡建立dfs的作用:dfs來判斷當前root,和當前word[i]下是能否查得到詞,所以返回是bool型別的
                (並且可以遞迴地來看查詞這個事兒'bad'這個詞查詢,可以分解為'b'->'a'->'d')
                所以條件應該是if dfs(next_leve) == True, return True,否則,就等所有情況都不滿足,都沒有return True
                的話,再return False,這裡的邏輯是,如果都沒有,才False
            如此便可以根據此在word[i] 是否為'.'構建遞迴
            但是還不夠,還需要確定程式遞迴到底層的出口,由於i每次向下+1,也就是每層遞迴是考慮下一個位置的i則最後如果i==len(word),
        就說明判斷到最後一個位置的字元之後了,為什麼說之後&是i==len(word)?因為Trie樹當前節點children儲存的是下一層的節點地址,
        如bad,判斷到d了,是'd' in curr_node.children,所以還要dfs到next_node中,即'd'指向的next_node位置,判斷next_node.isWord,
        符不符合查詢,直接return next_node.isWord即可
"""
class TrieNode:
    def __init__(self):
        self.children = {}
        self.isWord = False


class WordDictionary:

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

    def addWord(self, word):
        """
        Adds a word into the data structure.
        :type word: str
        :rtype: void
        """
        node = self.root
        for char in word:
            if char not in node.children:
                node.children[char] = TrieNode()
            node = node.children[char]
        node.isWord = True

    def search(self, word):
        """
        Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter.
        :type word: str
        :rtype: bool

        """

        def dfs(node, i):
            if i == len(word):
                return node.isWord
            if word[i] == '.':
                for next_node in node.children.values():
                    if dfs(next_node, i + 1):
                        return True
            else:
                if word[i] in node.children:
                    if dfs(node.children[word[i]], i + 1):
                        return True
            return False

        node = self.root
        return dfs(node, 0)