题目
思路一 暴力查找
使用哈希表存储每一个键值对,计算sum时就在哈希表里一个个找前缀符合的键,再获取值。
代码一
class MapSum {
public:
MapSum() {
}
void insert(string key, int val) {
mp[key]=val;
}
int sum(string prefix) {
int sum=0;
for(auto it=mp.begin();it!=mp.end();it++){
if((it->first).substr(0,prefix.size())==prefix)
sum+=it->second;
}
return sum;
}
private:
unordered_map<string,int> mp;
};
思路二 哈希表存储前缀
使用两个哈希表,一个哈希表存储键值对,一个哈希表存储前缀和以这个字符串为前缀的val和。sum函数可以直接返回第二个哈希表。每插入一个键值对,对其每一个前缀,更新值。更新的值有两种情况,第一种是如果这个key之前不存在,就直接加上现在的val,第二种是如果这个key之前存在,那么加上的需要是delta=val-原来的val。
代码二
class MapSum {
public:
MapSum() {
}
void insert(string key, int val) {
int delta=val;
if(map.count(key))
delta-=map[key];
map[key]=val;
for(int i=1;i<=key.size();i++){
prefixmap[key.substr(0,i)]+=delta;
}
}
int sum(string prefix) {
return prefixmap[prefix];
}
private:
unordered_map<string,int> map;
unordered_map<string,int> prefixmap;
};
思路三 Trie前缀树
定义一个前缀树的结构体,直接在前缀对应的 Trie 的每个节点存储该前缀对应的值。哈希表用来更新key对应的val,还有计算delta。每插入一个数,就顺着字符顺序一个个存下来,并给经过的每一个结点加上delta,如果不存在这个结点,就new一个结点。sum函数,循环,找到prefix对应的结点,并且返回val,如果prefix结点不存在就返回0.
代码三
struct TrieNode{
int val;
TrieNode *next[26];
TrieNode(){
this->val=0;
for(int i=0;i<26;i++){
this->next[i]=nullptr;
}
}
};
class MapSum {
public:
MapSum() {
this->root=new TrieNode();
}
void insert(string key, int val) {
int delta=val;
if(cnt.count(key)){
delta-=cnt[key];
}
cnt[key]=val;
TrieNode *node=root;
for(auto c:key){
if(node->next[c-'a']==nullptr)
node->next[c-'a']=new TrieNode();
node=node->next[c-'a'];
node->val+=delta;
}
}
int sum(string prefix) {
TrieNode* node=root;
for(auto c:prefix){
if(node->next[c-'a']==nullptr)
return 0;
else
node=node->next[c-'a'];
}
return node->val;
}
private:
TrieNode *root;
unordered_map<string,int> cnt;
};