題目地址:
https://leetcode.com/problems/add-and-search-word-data-structure-design/
設計一個數據結構,實現添加單詞,搜索單詞的功能。題目保證單詞都是小寫英文字母構成。搜索單詞的時候要允許搜索含.
通配符的單詞。
可以使用Trie來解決。添加單詞和Trie裏的實現一模一樣,可以參考https://blog.csdn.net/qq_46105170/article/details/105902984。搜索單詞的時候由於需要考慮通配符,所以要採用DFS的方式。當遇到.
的時候,要對每一個branch都進行搜索,看看是否存在滿足條件的單詞。代碼如下:
import java.util.HashMap;
import java.util.Map;
public class WordDictionary {
class Node {
boolean isWord;
Map<Character, Node> next;
Node() {
next = new HashMap<>();
}
}
private Node root;
/** Initialize your data structure here. */
public WordDictionary() {
root = new Node();
}
/** Adds a word into the data structure. */
public void addWord(String word) {
Node cur = root;
for (int i = 0; i < word.length(); i++) {
char c = word.charAt(i);
if (!cur.next.containsKey(c)) {
cur.next.put(c, new Node());
}
cur = cur.next.get(c);
}
cur.isWord = true;
}
/** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */
public boolean search(String word) {
return dfs(root, word, 0);
}
// 表示在以node爲根的子樹裏,尋找word[start: ]是否存在
private boolean dfs(Node node, String word, int start) {
// 如果已經找到了單詞末尾,則只需要看當前node是否標記爲單詞結尾
if (start == word.length()) {
return node.isWord;
}
// 否則取出當前字母
char c = word.charAt(start);
if (c != '.') {
// 如果c不是通配符,那麼說明是字母,看一下該字母的分叉是否存在,
// 若不存在,說明不存在要找的單詞,返回false;否則走到下一個node,遞歸尋找剩餘子串
if (!node.next.containsKey(c)) {
return false;
} else {
return dfs(node.next.get(c), word, start + 1);
}
} else {
// 若是通配符,那麼需要遍歷從node開始的所有分叉,只需找到一個就返回true,
// 若都未找到說明不存在,則返回false
for (Map.Entry<Character, Node> entry : node.next.entrySet()) {
if (dfs(entry.getValue(), word, start + 1)) {
return true;
}
}
return false;
}
}
}
addWord()
時間複雜度,search()
若參數沒有通配符,則時間複雜度是,若有,則會達到,其中是通配符的個數。空間複雜度與單詞具體什麼樣有關。
由於題目保證只有小寫英文字母了,所以Node裏的next可以換成數組,以加快速度。代碼如下:
public class WordDictionary {
class Node {
boolean isWord;
Node[] next;
Node() {
next = new Node[26];
}
}
Node root;
/** Initialize your data structure here. */
public WordDictionary() {
root = new Node();
}
/** Adds a word into the data structure. */
public void addWord(String word) {
Node cur = root;
for (int i = 0; i < word.length(); i++) {
char c = word.charAt(i);
if (cur.next[c - 'a'] == null) {
cur.next[c - 'a'] = new Node();
}
cur = cur.next[c - 'a'];
}
cur.isWord = true;
}
/** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */
public boolean search(String word) {
return dfs(root, word, 0);
}
private boolean dfs(Node node, String word, int start) {
if (start == word.length()) {
return node.isWord;
}
char c = word.charAt(start);
if (c != '.') {
if (node.next[c - 'a'] == null) {
return false;
} else {
return dfs(node.next[c - 'a'], word, start + 1);
}
} else {
for (int i = 0; i < node.next.length; i++) {
if (node.next[i] != null && dfs(node.next[i], word, start + 1)) {
return true;
}
}
return false;
}
}
}