1. 問題描述:
給你一個產品數組 products 和一個字符串 searchWord ,products 數組中每個產品都是一個字符串。
請你設計一個推薦系統,在依次輸入單詞 searchWord 的每一個字母后,推薦 products 數組中前綴與 searchWord 相同的最多三個產品。如果前綴相同的可推薦產品超過三個,請按字典序返回最小的三個。
請你以二維列表的形式,返回在輸入 searchWord 每個字母后相應的推薦產品的列表。
示例 1:
輸入:products = ["mobile","mouse","moneypot","monitor","mousepad"], searchWord = "mouse"
輸出:[
["mobile","moneypot","monitor"],
["mobile","moneypot","monitor"],
["mouse","mousepad"],
["mouse","mousepad"],
["mouse","mousepad"]
]
解釋:按字典序排序後的產品列表是 ["mobile","moneypot","monitor","mouse","mousepad"]
輸入 m 和 mo,由於所有產品的前綴都相同,所以系統返回字典序最小的三個產品 ["mobile","moneypot","monitor"]
輸入 mou, mous 和 mouse 後系統都返回 ["mouse","mousepad"]
示例 2:
輸入:products = ["havana"], searchWord = "havana"
輸出:[["havana"],["havana"],["havana"],["havana"],["havana"],["havana"]]
示例 3:
輸入:products = ["bags","baggage","banner","box","cloths"], searchWord = "bags"
輸出:[["baggage","bags","banner"],["baggage","bags","banner"],["baggage","bags"],["bags"]]
示例 4:
輸入:products = ["havana"], searchWord = "tatiana"
輸出:[[],[],[],[],[],[],[]]
提示:
1 <= products.length <= 1000
1 <= Σ products[i].length <= 2 * 10^4
products[i] 中所有的字符都是小寫英文字母。
1 <= searchWord.length <= 1000
searchWord 中所有字符都是小寫英文字母。
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/search-suggestions-system
2. 思路分析:
① 對於這種問題的比較常規的方法是使用字典樹來進行解決,我們在循環遍歷這些products單詞的時候就創建字典樹,所以我們通過當前的單詞構建字典樹的時候需要遍歷當前單詞的所有字母,通過單詞中的字母可以看成是前綴來完善字典樹,對於字典樹我們可以通過簡單的例子來畫出具體的字典樹這樣會更好理解一點,下面是products = ["abc", "abd", "abf"], searchWord = "abf"的構建出來的字典樹
② 其實畫出對應的字典樹,並且在循環中更新當前的根節點那麼就可以不斷完善出字典樹,最後我們只需要遍歷出字典樹中對應的單詞即可
3. 代碼如下:
下面是官方提供的代碼(自己做了一些註釋)
class Trie:
# 相當於Java中的構造器調用這個函數返回的是這個對象
def __init__(self):
self.child = dict()
self.words = list()
class Solution:
def suggestedProducts(self, products: List[str], searchWord: str) -> List[List[str]]:
# 這道題目可能與之前有不同的思路, 值得學習一下 可以使用字典樹進行解決
# 可以畫出具體的一棵樹來進行理解
def addWord(root, word):
cur = root
for ch in word:
if ch not in cur.child:
cur.child[ch] = Trie()
# 下一次循環的時候當前的孩子爲根, 所以需要修改的根爲當前的孩子節點
cur = cur.child[ch]
cur.words.append(word)
cur.words.sort()
if len(cur.words) > 3:
cur.words.pop()
# 返回的是一個對象來的
root = Trie()
for word in products:
addWord(root, word)
# 使用list函數創建一個空的list列表
ans = list()
cur = root
# 設計標記的目的是爲了在第一個字母不匹配的時候直接創建空列表即可
flag = False
for ch in searchWord:
if flag or ch not in cur.child:
ans.append(list())
flag = True
else:
cur = cur.child[ch]
ans.append(cur.words)
return ans