Given an array of strings products
and a string searchWord
. We want to design a system that suggests at most three product names from products
after each character of searchWord
is typed. Suggested products should have common prefix with the searchWord. If there are more than three products with a common prefix return the three lexicographically minimums products.
Return list of lists of the suggested products
after each character of searchWord
is typed.
Example 1:
Input: products = ["mobile","mouse","moneypot","monitor","mousepad"], searchWord = "mouse" Output: [ ["mobile","moneypot","monitor"], ["mobile","moneypot","monitor"], ["mouse","mousepad"], ["mouse","mousepad"], ["mouse","mousepad"] ] Explanation: products sorted lexicographically = ["mobile","moneypot","monitor","mouse","mousepad"] After typing m and mo all products match and we show user ["mobile","moneypot","monitor"] After typing mou, mous and mouse the system suggests ["mouse","mousepad"]
Example 2:
Input: products = ["havana"], searchWord = "havana" Output: [["havana"],["havana"],["havana"],["havana"],["havana"],["havana"]]
Example 3:
Input: products = ["bags","baggage","banner","box","cloths"], searchWord = "bags" Output: [["baggage","bags","banner"],["baggage","bags","banner"],["baggage","bags"],["bags"]]
Example 4:
Input: products = ["havana"], searchWord = "tatiana" Output: [[],[],[],[],[],[],[]]
Constraints:
1 <= products.length <= 1000
- There are no repeated elements in
products
. 1 <= Σ products[i].length <= 2 * 10^4
- All characters of
products[i]
are lower-case English letters. 1 <= searchWord.length <= 1000
- All characters of
searchWord
are lower-case English letters.
看到这样的题目很自然地想到了前缀树(Trie)。还是以LeetCode 208. Implement Trie (Prefix Tree) 为基础。前缀树Trie数据结构定义和单词插入都一样。区别还是查找条件,对于一个单词依次输入一个字母,每次输入一个字母形成该单词的前缀字符串,要求返回前缀树里与该前缀相匹配的3个单词。
从头开始扫描输入单词,每增加一个字母就形成一个新的前缀,前缀的每个字母都对应树里一个节点(如果没有匹配节点表示从该字母开始以后都没有匹配的节点,即每次答案都是空列表即0个相匹配单词),从前缀字符串最后一个字母对应的节点开始搜索整棵字母,找到3个单词(根据前缀树特点,最先找到的三个单词就为字母顺序排序最小的三个单词),然后把找到的3个(可能不够三个或为空)单词列表更新进结果列表。
class TrieNode:
def __init__(self):
self.end = False
self.children = [None] * 26
class Solution:
def suggestedProducts(self, products: List[str], searchWord: str) -> List[List[str]]:
root = TrieNode()
for word in products:
node = root
for c in word:
idx = ord(c) - ord('a')
if not node.children[idx]:
node.children[idx] = TrieNode()
node = node.children[idx]
node.end = True
res = []
node = root
word = ''
for c in searchWord:
ans = []
i = ord(c) - ord('a')
if not node or not node.children[i]:
node = None
res.append(ans)
continue
node = node.children[i]
word += c
self.search(node, word, ans)
res.append(ans)
return res
def search(self, root, word, ans):
if len(ans) == 3:
return
if root.end:
ans.append(word)
for i in range(26):
if not root.children[i]:
continue
tmp = word + chr(ord('a') + i)
self.search(root.children[i], tmp, ans)
注:本文是为了熟练掌握前缀树,而前缀并非本题的最优解法。网上有大神用二分法查找来解答这题非常简洁和高效,大家可以搜索参考。