# [LeetCode 677. Map Sum Pairs ](https://leetcode.com/explore/challenge/card/july-leetcoding-challenge-2021/612/week-5-july-29th-july-31st/3832/) ### Daily challenge Jul 30, 2021 (MEDIAN) >Implement the `MapSum` class: > >* **`MapSum()`** Initializes the `MapSum` object. >* **`void insert(String key, int val)`** Inserts the `key-val` pair into the map. If the `key` already existed, the original `key-value` pair will be overridden to the new one. >* **`int sum(string prefix)`** Returns the sum of all the pairs' value whose `key` starts with the `prefix`. :::info **Example 1:** **Input** ["MapSum", "insert", "sum", "insert", "sum"] [[], ["apple", 3], ["ap"], ["app", 2], ["ap"]] **Output** [null, null, 3, null, 5] **Explanation** MapSum mapSum = new MapSum(); mapSum.insert("apple", 3); mapSum.sum("ap"); // return 3 (apple = 3) mapSum.insert("app", 2); mapSum.sum("ap"); // return 5 (apple + app = 3 + 2 = 5) ::: :::warning **Constraints:** * 1 <= key.length, prefix.length <= 50 * key and prefix consist of only lowercase English letters. * 1 <= val <= 1000 * At most 50 calls will be made to insert and sum. ::: --- ### Approach 1 : Hash Map :bulb: **`4 ms ( 68.72% )`** **`Insert ---> O(1)`** **`Sum ---> O(K * P)`** `K、P are length of key & prefix` * **insert** : `map` 只記錄輸入的 `key、val`。 * **sum** : 從 `map` 中遍歷每個 `map.first`,判斷他的開頭是否與 `prefix` 相同。 ```cpp=1 class MapSum { public: /** Initialize your data structure here. */ MapSum() { } void insert(string key, int val) { list[key] = val; } bool check(string key, string prefix){ int size_pre = prefix.length(); int size_key = key.length(); if(size_key < size_pre) return false; for(int i=0; i<size_pre; i++){ if(key[i] != prefix[i]) return false; } return true; } int sum(string prefix) { int ans = 0; for(auto LIST : list){ string key = LIST.first; if(check(key, prefix)) ans += LIST.second; } return ans; } private: unordered_map<string, int> list; }; /** * Your MapSum object will be instantiated and called as such: * MapSum* obj = new MapSum(); * obj->insert(key,val); * int param_2 = obj->sum(prefix); */ ``` --- ### Approach 2 : Trie :book: **`0 ms ( 100% )`** **`Insert ---> O(K)`** **`Sum ---> O(P)`** :::success ![](https://i.imgur.com/NSqJ7kb.png) ::: * 一開始先宣告一個 `TrieNode root`。 * **insert** : > 1. `dif` 表示與原本字串 `val` 的差值 ---> **`dif = val - used[key]`**。 > ( 因為規定 `insert` 相同字串時,原本的 `val` 會被覆蓋掉 ) > 2. 遍歷 `key` 內所有的元素, >>* `建立新的 TrieNode` ( 若指到 `node` 為空 ) >>---> **`current->node[c] = new TrieNode()`**。 >>* `更改 val` ---> **`current = current->node[c]()`**。 >>* `更新 current` ---> **`current = current->node[c]`**。 > 3. 最後將 `key` 記錄到 `map`。 * sum : > 根據 `prefix` 的字元向下搜尋 `node` >> * 若 **`current->node[c] == NULL`**,表示沒有該字串 ---> 回傳 **`0`**。 >> * 若能找到 ---> 回傳 **`current->sum`**。 ```cpp=1 struct TrieNode{ TrieNode* node[26] = {}; int sum = 0; }; class MapSum { public: unordered_map<string, int> used; TrieNode root; MapSum() { } void insert(string key, int val) { TrieNode* current = &root; int dif = val - used[key]; for(char c : key){ c -= 'a'; if(current->node[c] == NULL) current->node[c] = new TrieNode(); current = current->node[c]; current->sum += dif; } used[key] = val; } int sum(string prefix) { TrieNode* current = &root; for(char c : prefix){ c -= 'a'; if(current->node[c] == NULL) return 0; current = current->node[c]; } return current->sum; } }; ``` --- ### Approach 3 : Trie + Hash Map :book: **`0 ms ( 100% )`** **`Insert ---> O(K^2)`** **`Sum ---> O(1)`** * **insert** : 與 `Approach 2` 相似。 > 1. **`dif = val - used[key]`** 表示與原本字串 `val` 的差值。 > 2. 將 `key` 存入 `used` ---> **`used[key] = val;`**。 > 3. 遍歷 `key`,將所有可能的 `prefix` 存入 `SUM` ---> **`SUM[prefix] += dif`**。 * **sum** : 直接回傳 `SUM[prefix]` ```cpp=1 class MapSum { public: unordered_map<string, int> used; unordered_map<string, int> SUM; MapSum() { } void insert(string key, int val) { int dif = val - used[key]; used[key] = val; string prefix; for(char c : key){ prefix += c; SUM[prefix] += dif; } } int sum(string prefix) { return SUM[prefix]; } }; ```