Map Sum Pairs 鍵值對映
阿新 • • 發佈:2018-12-13
實現一個 MapSum 類裡的兩個方法,insert
和 sum
。
對於方法 insert
,你將得到一對(字串,整數)的鍵值對。字串表示鍵,整數表示值。如果鍵已經存在,那麼原來的鍵值對將被替代成新的鍵值對。
對於方法 sum
,你將得到一個表示字首的字串,你需要返回所有以該字首開頭的鍵的值的總和。
示例 1:
輸入: insert("apple", 3), 輸出: Null
輸入: sum("ap"), 輸出: 3
輸入: insert("app", 2), 輸出: Null
輸入: sum("ap"), 輸出: 5
思路一:構建一個詞典字首樹,構建的方法參見Implement Trie (Prefix Tree) 實現 Trie (字首樹)
參考程式碼如下:
class MapSum { struct Trie { bool isWord; Trie* children[26] = {}; Trie() :isWord(false) { for (auto &child : children) child = nullptr; } }; class TrieNode { public: TrieNode() { root = new Trie(); } void insert(string &word) { Trie *p = root; for (auto &ch : word) { if (!p->children[ch - 'a']) p->children[ch - 'a'] = new Trie(); p = p->children[ch - 'a']; } p->isWord = true; } void packageInsert(string word, int val) { insert(word); m[word] = val; } void dfs(Trie* p,int &sum, string tmp) { if (p->isWord) { sum += m[tmp]; } for (int i = 0; i < 26; i++) { char ch = ('a' + i); if (p->children[i]) dfs(p->children[i], sum, tmp + ch); } } int searchPrefix(string &pre) { int res=0; Trie *p = root; string tmp; for (auto &ch : pre) { if (!p->children[ch - 'a']) return res; p = p->children[ch - 'a']; } tmp = pre; dfs(p, res, tmp); return res; } private: Trie * root; unordered_map<string, int> m; }; public: /** Initialize your data structure here. */ MapSum() { node = new TrieNode(); } void insert(string key, int val) { node->packageInsert(key, val); } int sum(string prefix) { return node->searchPrefix(prefix); } private: TrieNode * node; };
思路二:需要兩個hashmap,m和score,其中m儲存每一個輸入的<string,int>的對應關係,而score直接儲存對應prefix的分數,具體做法為每當有insert操作時,我們計算一個delta值=val-m[string],然後對string的每一個char都更新這個score,即如下核心程式碼:
void insert(string key, int val) { int delta = val - m[key]; m[key] = val; string prefix = ""; for (auto &ch : key) { prefix += ch; score[prefix] = ((score.find(prefix)==score.end())?0:score[prefix] + delta); } }
相當於我們儲存每一個string的所有第一個字元開始的子序列的分數,並且這個操作的巧妙之處在於可以完成:覆蓋和替換的功能,那麼當呼叫sum函式時,我們直接返回score[prefix]即可。
參考程式碼如下:
class MapSum {
public:
/** Initialize your data structure here. */
MapSum() {
}
void insert(string key, int val) {
int delta = val - m[key];
m[key] = val;
string prefix = "";
for (auto &ch : key) {
prefix += ch;
score[prefix] = ((score.find(prefix)==score.end())?0:score[prefix] + delta);
}
}
int sum(string prefix) {
return score[prefix];
}
private:
unordered_map<string, int> m;
unordered_map<string, int> score;
};
/**
* Your MapSum object will be instantiated and called as such:
* MapSum obj = new MapSum();
* obj.insert(key,val);
* int param_2 = obj.sum(prefix);
*/