题目描述:
实现一个 MapSum 类,支持两个方法,insert 和 sum:
MapSum() 初始化 MapSum 对象
void insert(String key, int val) 插入 key-val 键值对,字符串表示键 key ,整数表示值 val 。如果键 key 已经存在,那么原来的键值对将被替代成新的键值对。
int sum(string prefix) 返回所有以该前缀 prefix 开头的键 key 的值的总和。
示例:
输入:
[“MapSum”, “insert”, “sum”, “insert”, “sum”]
[[], [“apple”, 3], [“ap”], [“app”, 2], [“ap”]]
输出:
[null, null, 3, null, 5]
解释:
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)
提示:
1 <= key.length, prefix.length <= 50
key 和 prefix 仅由小写英文字母组成
1 <= val <= 1000
最多调用 50 次 insert 和 sum
方法1:
主要思路:解题汇总链接
(1)使用前缀树;
(2)对于前缀树的每个前缀存储该前缀下的所有的结点之和;
(3)为了能够在插入某个键值时,快速更新前缀树的各个结点之和,使用unordered_map<string,int>存储键对应的值,先判读存在性,再根据此次对应的值,进行更新,算出实际需要插入的值,再对前缀树进行遍历更新;
class MapSum {
public:
struct Node{
vector<Node*> next;//各个结点的指针
vector<int>val;//各个指针下的路径的前缀和
Node(){
val=vector<int>(26,0);
next=vector<Node*>(26,NULL);
}
};
/** Initialize your data structure here. */
Node* root;
unordered_map<string,int> mp;//存储键值
MapSum() {
root=new Node();
}
void insert(string key, int val) {
Node* cur=root;
if(mp.count(key)){//判断键的存在性,并进行键和值的更新
int tmp=val;
val-=mp[key];
mp[key]=tmp;
}
else{
mp[key]=val;
}
//更新前缀树
for(char&ch:key){
if(cur->next[ch-'a']==NULL){
cur->next[ch-'a']=new Node(); //若不存在,则建立新的结点
}
cur->val[ch-'a']+=val;
cur=cur->next[ch-'a'];
}
}
//找给出的前缀的和
int sum(string prefix) {
int sum=0;
Node* cur=root;
for(char&ch:prefix){
sum=cur->val[ch-'a'];//更新该值
cur=cur->next[ch-'a'];
if(cur==NULL){//若已经是空,则终止循环
break;
}
}
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);
*/