📖Blog :《LeetCode 211.添加與搜索單詞(數據結構設計) - JavaScript》javascript
題目描述:設計一個支持如下兩種操做的數據結構:java
void addWord(word) bool search(word)
search(word)
能夠搜索文字或正則表達式字符串,字符串只包含字母 .
或 a-z
。 .
能夠表示任何一個字母。node
示例:python
addWord("bad") addWord("dad") addWord("mad") search("pad") -> false search("bad") -> true search(".ad") -> true search("b..") -> true
你能夠假設全部單詞都是由小寫字母 a-z
組成的。git
看到題目,第一個直覺是將單詞都存放在數組中。每次匹配的時候,循環遍歷數組,查看是否存在能夠匹配的字符串。github
可是這種暴力法的時間複雜度高,在平臺上沒法 ac。所以要想其餘的方法。正則表達式
有一種很是巧妙的正則表達式方法:全部的單詞再也不存放在數組中,而是經過先後添加「#」來進行分割(標識單詞界限)。數組
例如依次添加了「bad」、「mad」。那麼內部字符串是:「#bad#mad#」。當咱們要匹配目標串「.ad」時,只須要在目標串先後添加「#」便可。數據結構
在 leetcode 上,本題的 js 寫法沒法 ac,可是 python3 的能夠。應該是斷定條件比較寬鬆,下面的代碼 ac 花費了 2924ms。this
# ac地址: https://leetcode-cn.com/problems/add-and-search-word-data-structure-design/ # 原文地址:https://xxoo521.com/2020-02-29-add-and-search-word/ from re import search class WordDictionary: def __init__(self): """ Initialize your data structure here. """ self.words = '#' def addWord(self, word: str) -> None: """ Adds a word into the data structure. """ self.words += (word + '#') def search(self, word: str) -> bool: """ Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. """ return bool(search('#' + word + '#', self.words))
對於記錄/查找單詞的情景,有種數據結構很是高效:Trie。咱們能夠構造一棵字典樹,每次調用 addWord 時候,將單詞存入字典樹。
注意:當調用 search 進行查找的時候,若是當前字符不是.
,那麼就按照字典樹的查找邏輯;不然,因爲是通配符,要遍歷當前的節點的 next 中的全部字符,這個過程和 DFS 同樣。
代碼以下:
// ac地址: https://leetcode-cn.com/problems/add-and-search-word-data-structure-design/ // 原文地址:https://xxoo521.com/2020-02-29-add-and-search-word/ var TrieNode = function() { this.next = {}; this.isEnd = false; }; /** * Initialize your data structure here. */ var WordDictionary = function() { this.root = new TrieNode(); }; /** * @param {string} word * @return {void} */ WordDictionary.prototype.addWord = function(word) { if (!word.length) return; let node = this.root; for (let i = 0; i < word.length; ++i) { if (!node.next[word[i]]) { node.next[word[i]] = new TrieNode(); } node = node.next[word[i]]; } node.isEnd = true; }; /** * @param {string} word * @return {boolean} */ WordDictionary.prototype.search = function(word) { if (!word.length) return false; return this.dfs(this.root, word); }; /** * @param {TrieNode} root * @param {string} word * @return {boolean} */ WordDictionary.prototype.dfs = function(root, word) { const length = word.length; let node = root; for (let i = 0; i < length; ++i) { const ch = word[i]; // 如果通配符,則嘗試遍歷全部的狀況(DFS) if (ch === ".") { const keys = Reflect.ownKeys(node.next); for (const key of keys) { const found = this.dfs(node.next[key], word.slice(i + 1)); if (found) return true; } return false; } if (!node.next[ch]) { return false; } node = node.next[ch]; } return node.isEnd; };
如有錯誤,歡迎指正。若對您有幫助,請給個「關注+點贊」,您的支持是我更新的動力 👇