LeetCode 211.添加與搜索單詞(數據結構設計)

📖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。所以要想其餘的方法。正則表達式

解法 1: 巧妙的正則表達式

有一種很是巧妙的正則表達式方法:全部的單詞再也不存放在數組中,而是經過先後添加「#」來進行分割(標識單詞界限)數組

例如依次添加了「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))

解法 2: 字典樹(Trie)+ DFS

對於記錄/查找單詞的情景,有種數據結構很是高效: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;
};

更多資料

如有錯誤,歡迎指正。若對您有幫助,請給個「關注+點贊」,您的支持是我更新的動力 👇

相關文章
相關標籤/搜索