目录
一、题目描述
实现一个 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
二 、解题思路
这道题是在字典树的基础上加了一点难度。之所以想到用字典树是因为需要搜索字符前缀,构建字典树,匹配前缀正是字典树擅长的操作。
插入操作:
在字典树插入的基础上还需添加对数值的处理,每个节点增加一个int类型的val属性,在插入字符串的结尾节点时保存这个值,非字符串结尾节点的val值为0。
求和操作:
从前缀的最后一个节点开始需要遍历后续所有可达的字符串,把每个结尾节点的val值相加。这里需要使用深度优先遍历,不断地往下遍历每一个字符串。
三、代码实现
#include<bits/stdc++.h>
using namespace std;
//字典树节点的结构
//指针数组形式
class node {
public:
node* trieNode[26];
bool isEnd;
int val;
node() {
memset(trieNode, 0, sizeof(trieNode));
isEnd = false;
val = 0;
}
~node() {
for (int i = 0; i < 26; i++) {
if (trieNode[i]) {
delete trieNode[i];
}
}
}
};
class MapSum {
public:
//树根节点
node* root;
/** Initialize your data structure here. */
MapSum() {
root = new node();
}
void insert(string key, int val) {
node *p = root;
int n = key.size();
for (int i = 0; i < n; i++) {
int c = key[i] - 'a';
if (!p->trieNode[c]) {
p->trieNode[c] = new node();
}
p = p->trieNode[c];
}
p->isEnd = true;
//结尾节点更新val值
p->val = val;
}
int sum(string prefix) {
int n = prefix.size();
node* p = root;
for (int i = 0; i < n; i++) {
int c = prefix[i] - 'a';
if (!p->trieNode[c]) {
return 0;
}
p = p->trieNode[c];
}
//递归计算后续所有的节点
return dfs(p);
}
private:
int dfs(node* p) {
//递归出口
if (!p) return 0;
int res = 0;
//增加每一个符合要求的val
if (p->isEnd) res += p->val;
for (int i = 0; i < 26; i++) {
res += dfs(p->trieNode[i]);
}
return res;
}
};
/**
* Your MapSum object will be instantiated and called as such:
* MapSum* obj = new MapSum();
* obj->insert(key,val);
* int param_2 = obj->sum(prefix);
*/
int main() {
int n = 2;
MapSum* mapSum = new MapSum();
string str;
int a;
while (n--) {
cin >> str;
cin >> a;
mapSum->insert(str, a);
cout << mapSum->sum("ap")<<endl;
}
return 0;
}