leetcode - 1268. Search Suggestions System

Description

You are given an array of strings products and a string searchWord.

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 searchWord. If there are more than three products with a common prefix return the three lexicographically minimums products.

Return a 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"]]
Explanation: The only word "havana" will be always suggested while typing the search word.

Constraints:

1 <= products.length <= 1000
1 <= products[i].length <= 3000
1 <= sum(products[i].length) <= 2 * 10^4
All the strings of products are unique.
products[i] consists of lowercase English letters.
1 <= searchWord.length <= 1000
searchWord consists of lowercase English letters.

Solution

Solved after help.

TrieTree

For searching top frequent words, it’s implemented by using a heap to store all the possible words for each node. Since we need to return all the smallest words, we use a max-heap to store all the candidates.

How to build a max-heap for strings?
Use a self defined class like below:

class MaxHeapObj(str):
    def __init__(self, string):
        self.string = string
    def __lt__(self, other):
        return self.string > other.string
    def __eq__(self, other):
        return self.string == other.string

MaxHeapObj is a sub-class of str, and we changed the rule of <.

For this question, if the word doesn’t match anything in the TrieTree, then we return an empty list for suggestions.

Binary Search

Sort the product, and use sub strings from searchWord to search. All the products that are at the right of insert_index are possible suggestions, because they are “larger” than the sub-string, so they are either longer, or have same length but have “larger” alphabets. And we don’t want the latter one.

Time complexity: o ( n log ⁡ n ) o(n \log n) o(nlogn)
Space complexity: o ( n ) o(n) o(n)

Code

TrieTree

class MaxHeapObj(str):
    def __init__(self, string):
        self.string = string
    def __lt__(self, other):
        return self.string > other.string
    def __eq__(self, other):
        return self.string == other.string


class TrieNode:
    def __init__(self):
        self.children = {}
        self.suggestions = []
        self.is_end = False
    def add_suggestion(self, word: str) -> None:
        if len(self.suggestions) == 3:
            heapq.heappushpop(self.suggestions, MaxHeapObj(word))
        else:
            heapq.heappush(self.suggestions, MaxHeapObj(word))
    def get_suggestions(self):
        return sorted(self.suggestions, reverse=True)


class TrieTree:
    def __init__(self):
        self.root = TrieNode()

    def insert(self, word: str) -> None:
        node = self.root
        for each_char in word:
            if each_char not in node.children:
                node.children[each_char] = TrieNode()
            node = node.children[each_char]
            node.add_suggestion(word)
        node.is_end = True
    
    def get_suggestions(self, word: str) -> list:
        node = self.root
        i = 0
        while i < len(word):
            if word[i] not in node.children:
                break
            node = node.children[word[i]]
            i += 1
        return node.get_suggestions() if i == len(word) else []

class Solution:
    def suggestedProducts(self, products: List[str], searchWord: str) -> List[List[str]]:
        products.sort()
        trie_tree = TrieTree()
        for each_p in products:
            trie_tree.insert(each_p)
        res = []
        for i in range(len(searchWord)):
            res.append(trie_tree.get_suggestions(searchWord[:i + 1]))
        return res

Binary Search

class Solution:
    def suggestedProducts(self, products: List[str], searchWord: str) -> List[List[str]]:
        def find_match(word: str) -> list:
            left, right = 0, len(products) - 1
            while left < right:
                mid = (left + right) >> 1
                if products[mid] < word:
                    left = mid + 1
                else:
                    right = mid
            mid = (left + right) >> 1
            res = []
            for i in range(mid, min(mid + 3, len(products))):
                if products[i].startswith(word):
                    res.append(products[i])
            return res
        products.sort()
        res = []
        for i in range(len(searchWord)):
            res.append(find_match(searchWord[:i + 1]))
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值