Leetcode 642. Design Search Autocomplete System
Problem:
Design a search autocomplete system for a search engine. Users may input a sentence (at least one word and end with a special character '#'
). For each character they type except '#', you need to return the top 3 historical hot sentences that have prefix the same as the part of sentence already typed. Here are the specific rules:
- The hot degree for a sentence is defined as the number of times a user typed the exactly same sentence before.
- The returned top 3 hot sentences should be sorted by hot degree (The first is the hottest one). If several sentences have the same degree of hot, you need to use ASCII-code order (smaller one appears first).
- If less than 3 hot sentences exist, then just return as many as you can.
- When the input is a special character, it means the sentence ends, and in this case, you need to return an empty list.
Your job is to implement the following functions:
The constructor function:
AutocompleteSystem(String[] sentences, int[] times):
This is the constructor. The input is historical data. Sentences
is a string array consists of previously typed sentences. Times
is the corresponding times a sentence has been typed. Your system should record these historical data.
Now, the user wants to input a new sentence. The following function will provide the next character the user types:
List<String> input(char c):
The input c
is the next character typed by the user. The character will only be lower-case letters ('a'
to 'z'
), blank space (' '
) or a special character ('#'
). Also, the previously typed sentence should be recorded in your system. The output will be the top 3 historical hot sentences that have prefix the same as the part of sentence already typed.
Example:
Operation: AutocompleteSystem(["i love you", "island","ironman", "i love leetcode"], [5,3,2,2])
The system have already tracked down the following sentences and their corresponding times:
"i love you"
: 5
times
"island"
: 3
times
"ironman"
: 2
times
"i love leetcode"
: 2
times
Now, the user begins another search:
Operation: input('i')
Output: ["i love you", "island","i love leetcode"]
Explanation:
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.
Operation: input(' ')
Output: ["i love you","i love leetcode"]
Explanation:
There are only two sentences that have prefix "i "
.
Operation: input('a')
Output: []
Explanation:
There are no sentences that have prefix "i a"
.
Operation: input('#')
Output: []
Explanation:
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.
Note:
- The input sentence will always start with a letter and end with '#', and only one blank space will exist between two words.
- The number of complete sentences that to be searched won't exceed 100. The length of each sentence including those in the historical data won't exceed 100.
- Please use double-quote instead of single-quote when you write test cases even for a character input.
- Please remember to RESET your class variables declared in class AutocompleteSystem, as static/class variables are persisted across multiple test cases. Please see here for more details.
Solution:
这道题的难点在于,题目太长了。。。为了不再看第二遍,解释下题意。构造函数输入一堆句子以及它们出现的次数,然后input函数每次输入一个字符,找出历史输入加上现在输入的字符串为前缀的出现次数最多的3个句子,如果出现‘#’,则将当前的句子作为出现一次的句子添加到数据集中,然后将句子置为空。这道题可以不用Trie解决,last数据集用于记录上一次符合条件的字符串,因为后面输入一个字符,必然是从上一次数据集的子集,然后调用优先级队列找出频率前三的字符串即可
Code:
1 class AutocompleteSystem { 2 public: 3 struct mycompare{ 4 bool operator()(pair<int,string> &p1,pair<int,string> &p2){ 5 if(p1.first < p2.first) 6 return true; 7 else if(p1.first > p2.first) 8 return false; 9 else{ 10 return p1.second > p2.second; 11 } 12 } 13 }; 14 AutocompleteSystem(vector<string> sentences, vector<int> times) { 15 sentence = ""; 16 for(int i = 0;i != sentences.size();++i){ 17 count[sentences[i]] = times[i]; 18 } 19 } 20 21 vector<string> input(char c) { 22 if(c == '#'){ 23 count[sentence]++; 24 sentence = ""; 25 last.clear(); 26 return {}; 27 } 28 sentence += c; 29 if(sentence.size() == 1){ 30 for(auto iter:count){ 31 if(iter.first.at(0) == c) 32 last.insert(iter.first); 33 } 34 } 35 else{ 36 int m = sentence.size()-1; 37 auto iter = last.begin(); 38 while(iter != last.end()){ 39 string str = *iter; 40 if(str[m] != c) 41 iter = last.erase(iter); 42 else 43 iter++; 44 } 45 } 46 priority_queue<pair<int,string>,vector<pair<int,string>>,mycompare> pq; 47 for(auto str:last) 48 pq.push(make_pair(count[str],str)); 49 vector<string> result; 50 int k = 0; 51 while(!pq.empty() && k != 3){ 52 result.push_back(pq.top().second); 53 pq.pop(); 54 k++; 55 } 56 return result; 57 } 58 private: 59 unordered_set<string> last; 60 string sentence; 61 unordered_map<string,int> count; 62 }; 63 64 /** 65 * Your AutocompleteSystem object will be instantiated and called as such: 66 * AutocompleteSystem obj = new AutocompleteSystem(sentences, times); 67 * vector<string> param_1 = obj.input(c); 68 */