[LeetCode] 642. Design Search Autocomplete System_Hard tag: Trie

时间:2021-06-30 18:12:21   收藏:0   阅读:0

Design a search autocomplete system for a search engine. Users may input a sentence (at least one word and end with a special character ‘#‘).

You are given a string array sentences and an integer array times both of length n where sentences[i] is a previously typed sentence and times[i] is the corresponding number of times the sentence was typed. For each input character except ‘#‘, return the top 3 historical hot sentences that have the same prefix as the part of the sentence already typed.

Here are the specific rules:

Implement the AutocompleteSystem class:

 

Example 1:

Input
["AutocompleteSystem", "input", "input", "input", "input"]
[[["i love you", "island", "iroman", "i love leetcode"], [5, 3, 2, 2]], ["i"], [" "], ["a"], ["#"]]
Output
[null, ["i love you", "island", "i love leetcode"], ["i love you", "i love leetcode"], [], []]

Explanation
AutocompleteSystem obj = new AutocompleteSystem(["i love you", "island", "iroman", "i love leetcode"], [5, 3, 2, 2]);
obj.input("i"); // return ["i love you", "island", "i love leetcode"]. There are four sentences that have prefix "i". Among them, "ironman" and "i love leetcode" have same hot degree. Since ‘ ‘ has ASCII code 32 and ‘r‘ has ASCII code 114, "i love leetcode" should be in front of "ironman". Also we only need to output top 3 hot sentences, so "ironman" will be ignored.
obj.input(" "); // return ["i love you", "i love leetcode"]. There are only two sentences that have prefix "i ".
obj.input("a"); // return []. There are no sentences that have prefix "i a".
obj.input("#"); // return []. The user finished the input, the sentence "i a" should be saved as a historical sentence in system. And the following input will be counted as a new search.

 

Constraints:

 

Ideas: use Trie, 因为有rank,所以在Trie的基础上加入rank, 另外如果是isEnd,那么加入data去存目前的sentence, 然后在search的时候,先看是不是有prefix,如果有的话,最后通过dfs去找到所有prefix 的sentence,然后将(freq, sentence) append进入到ans里面,最后sort,因为我们需要freq从高到低,所以rank我们存的都是负值。

self.keyWord用于存储目前所看到的sentence直到看到‘#’

 

Code

class TrieNode:
    def __init__(self):
        self.isEnd = False
        self.children = dict()
        self.data = None
        self.rank = 0
        
class AutocompleteSystem:

    def __init__(self, sentences: List[str], times: List[int]):
        self.root = TrieNode()
        self.keyWord = ""
        for index, sentence in enumerate(sentences):
            self.insert(sentence, times[index])
    
    def insert(self, sentence, hot):
        node = self.root
        for c in sentence:
            if c not in node.children:
                node.children[c] = TrieNode()
            node = node.children[c]
        node.isEnd = True
        node.data = sentence
        node.rank -= hot  # we need get decrease order for rank
    
    def search(self, sentence):
        node = self.root
        for c in sentence:
            if c not in node.children:
                return []
            node = node.children[c]
        return self.dfs(node)
    
    def dfs(self, root):
        if not root: return []
        ans = []
        if root.isEnd:
            ans.append((root.rank, root.data))
        for child in root.children:
            ans += self.dfs(root.children[child])
        return ans

    def input(self, c: str) -> List[str]:
        ans = []
        if c != ‘#‘:
            self.keyWord += c
            ans = self.search(self.keyWord)
        else:
            self.insert(self.keyWord, 1)
            self.keyWord = ""
        return [each[1] for each in sorted(ans)[:3]]
        


# Your AutocompleteSystem object will be instantiated and called as such:
# obj = AutocompleteSystem(sentences, times)
# param_1 = obj.input(c)

 

评论(0)
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!