[LeetCode] Map Sum Pairs 映射配對之和
Implement a MapSum class with insert
, and sum
methods.
For the method insert
, you‘ll be given a pair of (string, integer). The string represents the key and the integer represents the value. If the key already existed, then the original key-value pair will be overridden to the new one.
For the method sum
Example 1:
Input: insert("apple", 3), Output: Null Input: sum("ap"), Output: 3 Input: insert("app", 2), Output: Null Input: sum("ap"), Output: 5
這道題讓我們實現一個MapSum類,裏面有兩個方法,insert和sum,其中inser就是插入一個鍵值對,而sum方法比較特別,是在找一個前綴,需要將所有有此前綴的單詞的值累加起來返回。看到這種玩前綴的題,照理來說是要用前綴樹來做的。但是博主一般想偷懶,不想新寫一個結構或類,於是就使用map來代替前綴樹啦。博主開始想到的方法是建立前綴和一個pair之間的映射,這裏的pair的第一個值表示該詞的值,第二個值表示將該詞作為前綴的所有詞的累加值,那麽我們的sum函數就異常的簡單了,直接將pair中的兩個值相加即可。關鍵就是要在insert中把數據結構建好,構建的方法也不難,首先我們suppose原本這個key是有值的,我們更新的時候只需要加上它的差值即可,就算key不存在默認就是0,算差值也沒問題。然後我們將first值更新為val,然後就是遍歷其所有的前綴了,給每個前綴的second都加上diff即可,參見代碼如下:
解法一:
class MapSum { public: /** Initialize your data structure here. */ MapSum() {} void insert(string key, int val) { int diff = val - m[key].first, n = key.size(); m[key].first = val; for (int i = n - 1; i > 0; --i) { m[key.substr(0, i)].second += diff; } } int sum(string prefix) { return m[prefix].first + m[prefix].second; } private: unordered_map<string, pair<int, int>> m; };
下面這種方法是論壇上投票最高的方法,感覺很叼,用的是帶排序的map,insert就是把單詞加入map。在map裏會按照字母順序自動排序,然後在sum函數裏,我們根據prefix來用二分查找快速定位到第一個不小於prefix的位置,然後向後遍歷,向後遍歷的都是以prefix為前綴的單詞,如果我們發現某個單詞不是以prefix為前綴了,直接break;否則就累加其val值,參見代碼如下:
解法二:
class MapSum { public: /** Initialize your data structure here. */ MapSum() {} void insert(string key, int val) { m[key] = val; } int sum(string prefix) { int res = 0, n = prefix.size(); for (auto it = m.lower_bound(prefix); it != m.end(); ++it) { if (it->first.substr(0, n) != prefix) break; res += it->second; } return res; } private: map<string, int> m; };
參考資料:
https://discuss.leetcode.com/topic/103924/java-map-solution
https://discuss.leetcode.com/topic/104006/c-easy-solution-ordered-map
LeetCode All in One 題目講解匯總(持續更新中...)
[LeetCode] Map Sum Pairs 映射配對之和