677. Map Sum Pairs(python+cpp)(包含字首樹解法)
阿新 • • 發佈:2018-11-23
題目:
Implement a MapSum class with
insert
, andsum
methods.
For the methodinsert
, 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 methodsum
, you’ll be given a string representing the prefix,and you need to return the sum of all the pairs’ value whose key starts with the prefix.
Example 1:Input: insert("apple", 3), Output: Null Input: sum("ap"), Output: 3 Input: insert("app", 2), Output: Null Input: sum("ap"), Output: 5
解釋:
這題可以用字典做,但是更經典的解法是
Trie
?字典解法,
1.在插入時直接插入,在求和是查詢所有字首,插入快
2.也可以在插入的時候記入所有字首,查詢快。
3.字首樹解法
第一種解法在c++中,可以利用map對key排序的特點,map.lower_bound(prefix)就可以得到可能以prefix為字首的最小鍵值對,然後從這裡開始遍歷,滿足條件便將其累加,不滿足條件則可以終止遍歷。最後return累加值。
解法一:
python程式碼:
class MapSum(object):
def __init__(self):
"""
Initialize your data structure here.
"""
self._dict={}
def insert(self, key, val):
"""
:type key: str
:type val: int
:rtype: void
"""
self._dict[key]=val
def sum(self, prefix):
"""
:type prefix: str
:rtype: int
"""
result=0
for key in self._dict.keys():
if key.find(prefix)==0:
result+=self._dict[key]
return result
# Your MapSum object will be instantiated and called as such:
# obj = MapSum()
# obj.insert(key,val)
# param_2 = obj.sum(prefix)
c++程式碼:
#include <map>
using namespace std;
class MapSum {
public:
/** Initialize your data structure here. */
map<string,int>_map;
MapSum() {
}
void insert(string key, int val) {
_map[key]=val;
}
int sum(string prefix) {
int _sum=0;
for (auto it = _map.lower_bound(prefix); it != _map.end();it++){
if (it->first.find(prefix)==0)
_sum += it->second;
}
return _sum;
}
};
/**
* Your MapSum object will be instantiated and called as such:
* MapSum obj = new MapSum();
* obj.insert(key,val);
* int param_2 = obj.sum(prefix);
*/
判斷key是否以prefix開頭也可以用以下程式碼:
int sum = 0, len = prefix.size();
for (auto it = m.lower_bound(prefix); it != m.end();++it){
if (it->first.substr(0,len) == prefix)
sum += it->second;
}
return sum;
一個是查詢字串開始的位置,一個是從同一開始取指定長度的子字串看是否相等。
解法2:
python程式碼:
class MapSum(object):
def __init__(self):
"""
Initialize your data structure here.
"""
self._dict={}
self._sum={}
def insert(self, key, val):
"""
:type key: str
:type val: int
:rtype: void
"""
diff=val-self._dict.get(key,0)
for i in range(0,len(key)):
sub=key[:i+1]
self._sum[sub]=self._sum.get(sub,0)+diff
self._dict[key] =val
def sum(self, prefix):
"""
:type prefix: str
:rtype: int
"""
return self._sum.get(prefix,0)
# Your MapSum object will be instantiated and called as such:
# obj = MapSum()
# obj.insert(key,val)
# param_2 = obj.sum(prefix)
c++程式碼(速度沒有解法1快):
#include <map>
using namespace std;
class MapSum {
public:
/** Initialize your data structure here. */
map<string ,int>_map;
map<string ,int>_sum;
MapSum() {
}
void insert(string key, int val) {
int diff=val-_map[key];
for (int i=0;i<key.size();i++)
{
string sub=key.substr(0,i+1);
_sum[sub]+=diff;
}
_map[key]=val;
}
int sum(string prefix) {
return _sum[prefix];
}
};
/**
* Your MapSum object will be instantiated and called as such:
* MapSum obj = new MapSum();
* obj.insert(key,val);
* int param_2 = obj.sum(prefix);
*/
字首樹解法:
#感覺這道題是經典的字典樹問題
from collections import defaultdict
class TrieNode(object):
def __init__(self):
self.children=defaultdict(TrieNode)
self.isWord=False
self.freq=0
class MapSum(object):
def __init__(self):
"""
Initialize your data structure here.
"""
self.root=TrieNode()
self._dict={}
def insert(self, key, val):
"""
:type key: str
:type val: int
:rtype: void
"""
current=self.root
for letter in key:
current=current.children[letter]
current.freq+=val-self._dict.get(key,0)
current.isWord=True
self._dict[key]=val
def sum(self, prefix):
"""
:type prefix: str
:rtype: int
"""
current =self.root
for letter in prefix:
current=current.children.get(letter)
if current==None:
return 0
return current.freq
# Your MapSum object will be instantiated and called as such:
# obj = MapSum()
# obj.insert(key,val)
# param_2 = obj.sum(prefix)
c++程式碼:
#include <map>
using namespace std;
struct TrieNode{
bool isWord;
map<char,TrieNode*>children;
int freq;
TrieNode():isWord(false),freq(0) {};
};
class MapSum {
public:
/** Initialize your data structure here. */
TrieNode *root;
map<string,int>visited;
MapSum() {
root=new TrieNode();
}
void insert(string key, int val) {
TrieNode* current=root;
for(auto letter:key)
{
if (!current->children.count(letter))
current->children[letter]=new TrieNode();
current=current->children[letter];
current->freq+=val-visited[key];
}
current->isWord=true;
visited[key]=val;
}
int sum(string prefix) {
TrieNode* current=root;
for(auto letter:prefix)
{
if (!current->children.count(letter))
return 0;
current=current->children[letter];
}
return current->freq;
}
};
/**
* Your MapSum object will be instantiated and called as such:
* MapSum obj = new MapSum();
* obj.insert(key,val);
* int param_2 = obj.sum(prefix);
*/
總結: