分析题目:要求的结构需要唯一的键值,即如果先后输入【apple,3】【apple,2】最后在求sum的时候需要把原来的3删掉,而符合这一属性的结构,应该就是前缀树和哈希表的结合了。
class TrieNode{
public int pass;
public TrieNode[] nexts;
public TrieNode() {
pass = 0;
nexts = new TrieNode[26];
}
}
前缀树的结构,节点的属性有pass和nexts数组,节点和节点之间代表字符,即如果节点a到节点b的next【】数组不为null,即表示有值,pass代表经过这个节点的key有多少的val。
public void insert(String key, int val) {
int isInsert = map.getOrDefault(key,0);
map.put(key,val);
val = val - isInsert;
if(key==null){
return;
}
TrieNode cur = root;
cur.pass+=val;
for(char c:key.toCharArray()){
int index = c-'a';
if(cur.nexts[index]==null){
cur.nexts[index] = new TrieNode();
}
cur = cur.nexts[index];
cur.pass+=val;
}
}
因为要满足同时只有一个key在我的前缀树中,如果插入的key不是第一个,我就应该把原来key留下的痕迹删掉,这就有了前三句代码,如果之前没有重复的key,val的值不改变,如果有重复的值,val代表的是和原来的差距是多少,然后接下来就是弥补差距,此处可以动手模拟一下。
后边就是简单的前缀树逻辑了,但是要明白,本题中的前缀树,字符在树枝上,而不是节点上。
下面是完整代码
class MapSum {
private TrieNode root;
Map<String, Integer> map;
public MapSum() {
root = new TrieNode();
map = new HashMap<>();
}
public void insert(String key, int val) {
int isInsert = map.getOrDefault(key,0);
map.put(key,val);
val = val - isInsert;
if(key==null){
return;
}
TrieNode cur = root;
cur.pass+=val;
for(char c:key.toCharArray()){
int index = c-'a';
if(cur.nexts[index]==null){
cur.nexts[index] = new TrieNode();
}
cur = cur.nexts[index];
cur.pass+=val;
}
}
public int sum(String prefix) {
if(prefix==null){
return 0;
}
TrieNode cur = root;
char[] words = prefix.toCharArray();
for(char c:words){
int index = c-'a';
if(cur.nexts[index]==null){
return 0;
}
cur =cur.nexts[index];
}
return cur.pass;
}
}
class TrieNode{
public int pass;
public TrieNode[] nexts;
public TrieNode() {
pass = 0;
nexts = new TrieNode[26];
}
}
/**
* Your MapSum object will be instantiated and called as such:
* MapSum obj = new MapSum();
* obj.insert(key,val);
* int param_2 = obj.sum(prefix);
*/