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]]:
        products.sort()
        res = []
        for i in range(len(searchWord)):
            cur_word = searchWord[:i + 1]
            insert_index = bisect.bisect_left(products, cur_word)
            cur_res = []
            for next_i in range(insert_index, len(products)):
                if len(cur_res) == 3:
                    break
                if products[next_i].startswith(cur_word):
                    cur_res.append(products[next_i])
            res.append(cur_res.copy())
        return res

你可能感兴趣的:(OJ题目记录,leetcode,c#,算法)