Approach
Sorting and greedy selection
For Design Search Autocomplete System, the implementation first exposes a useful order, then scans that order while making locally justified choices.
- Choose the key that reveals the greedy or grouping structure.
- Sort the relevant records by that key.
- Scan in order, maintaining the invariant that makes each local choice safe.
Code notes
- 95 lines of C++ from the credited upstream file design-search-autocomplete-system.cpp.
- The implementation visibly relies on sequence storage, hash lookup.
- 4 loop blocks detected.
Complexity
Sorting is typically the dominant term unless the subsequent scan uses a more expensive nested operation.
Check the problem constraints before deciding whether this complexity will pass.
Use this to learn the idea, then write your own version.
1234 5class AutocompleteSystem {6public:7 AutocompleteSystem(vector<string> sentences, vector<int> times) : cur_node_(&trie_) {8 for (int i = 0; i < size(sentences); ++i) {9 sentence_to_count_[sentences[i]] = times[i];10 trie_.insert(sentences[i], sentence_to_count_[sentences[i]]);11 }12 }13 14 vector<string> input(char c) {15 vector<string> result;16 if (c == '#') {17 ++sentence_to_count_[search_];18 trie_.insert(search_, sentence_to_count_[search_]);19 cur_node_ = &trie_;20 search_.clear();21 } else {22 search_.push_back(c);23 if (cur_node_) {24 if (!cur_node_->leaves_.count(c)) {25 cur_node_ = nullptr;26 return {};27 }28 cur_node_ = cur_node_->leaves_[c];29 for (const auto& p : cur_node_->infos_) {30 result.emplace_back(p.second);31 }32 } 33 }34 return result;35 }36 37private:38 class TrieNode {39 public:40 static const int TOP_COUNT = 3;41 42 ~TrieNode() {43 for (auto& kv : leaves_) {44 if (kv.second) {45 delete kv.second;46 }47 }48 }49 50 51 void insert(const string& s, int times) {52 auto* cur = this;53 cur->add_info(s, times);54 for (const auto& c : s) {55 if (!cur->leaves_.count(c)) {56 cur->leaves_[c] = new TrieNode;57 }58 cur = cur->leaves_[c];59 cur->add_info(s, times);60 }61 }62 63 64 void add_info(const string& s, int times) {65 auto it = find_if(begin(infos_), end(infos_),66 [&s, ×](const pair<int, string>& p) {67 return p.second == s;68 } );69 if (it != end(infos_)) {70 it->first = -times;71 } else {72 infos_.emplace_back(-times, s);73 }74 sort(begin(infos_), end(infos_));75 if (size(infos_) > TOP_COUNT) {76 infos_.pop_back();77 }78 }79 80 vector<pair<int, string>> infos_;81 unordered_map<char, TrieNode *> leaves_;82 };83 84 TrieNode trie_;85 TrieNode *cur_node_;86 string search_;87 unordered_map<string, int> sentence_to_count_;88};89 90/**91 * Your AutocompleteSystem object will be instantiated and called as such:92 * AutocompleteSystem obj = new AutocompleteSystem(sentences, times);93 * vector<string> param_1 = obj.input(c);94 */95