677. Map Sum Pairs
题目描述和难度
- 题目描述:实现一个 MapSum 类里的两个方法,insert 和 sum。对于方法 insert,你将得到一对(字符串,整数)的键值对。字符串表示键,整数表示值。如果键已经存在,那么原来的键值对将被替代成新的键值对。对于方法 sum,你将得到一个表示前缀的字符串,你需要返回所有以该前缀开头的键的值的总和。
- 题目难度:中等。
- 英文网址:677. Map Sum Pairs 。
- 中文网址:677. 键值映射 。
思路分析
求解关键:使用 Trie
单词查找树这个数据结构来完成,将原来的 isWord
设计成 value
它不但可以表达原来 isWord
的含义,还能表示题目中一个单词携带的整数的含义。
+ 首先先把前缀遍历完,如果前缀都不能遍历完成,就说明单词查找树中不存在以这个单词为前缀的单词,应该返回 0,否则以一个结点为根,循环遍历到所有叶子节点,途径的所有 value 值都应该加和到最终的结果里。
+ 计算 sum 设计成一个递归方法,递归方法几行就完成了计算,虽然没有显式地写出递归终止条件,但递归终止条件已经包含在方法体中了。
参考解答
参考解答1
Java 写法:
import java.util.HashMap;
public class MapSum {
private Node root;
private class Node {
private int value;
private HashMap<Character, Node> next;
public Node() {
this(0);
}
public Node(int value) {
this.value = value;
this.next = new HashMap<>();
}
}
/**
* Initialize your data structure here.
*/
public MapSum() {
root = new Node();
}
public void insert(String key, int val) {
Node curNode = root;
for (int i = 0; i < key.length(); i++) {
Character c = key.charAt(i);
if (!curNode.next.containsKey(c)) {
curNode.next.put(c, new Node());
}
curNode = curNode.next.get(c);
}
curNode.value = val;
}
// 设计一个递归函数去完成它
public int sum(String prefix) {
Node curNode = root;
for (int i = 0; i < prefix.length(); i++) {
Character c = prefix.charAt(i);
if (curNode.next.containsKey(c)) {
curNode = curNode.next.get(c);
} else {
return 0;
}
}
return sum(curNode);
}
// 计算以 node 为根节点的所有 value 值的和
private int sum(Node node) {
int res = node.value;
for (Character key : node.next.keySet()) {
// 一直找到根节点
res += sum(node.next.get(key));
}
return res;
}
public static void main(String[] args) {
// 输入: insert("apple", 3), 输出: Null
// 输入: sum("ap"), 输出: 3
// 输入: insert("app", 2), 输出: Null
// 输入: sum("ap"), 输出: 5
MapSum2 mapSum = new MapSum2();
mapSum.insert("apple", 3);
int sum1 = mapSum.sum("ap");
System.out.println(sum1);
mapSum.insert("app", 2);
int sum2 = mapSum.sum("ap");
System.out.println(sum2);
}
}
Python 写法:
class MapSum(object):
# 设计成内部类,外部没有必要知道
class TrieNode:
def __init__(self):
self.val = 0
self.next = {}
def __init__(self):
"""
Initialize your data structure here.
"""
self.root = MapSum.TrieNode()
def insert(self, key, val):
"""
:type key: str
:type val: int
:rtype: void
"""
cur_node = self.root
for c in key:
if c not in cur_node.next.keys():
cur_node.next[c] = MapSum.TrieNode()
cur_node = cur_node.next[c]
cur_node.val = val
def sum(self, prefix):
"""
:type prefix: str
:rtype: int
"""
cur_node = self.root
for c in prefix:
if c in cur_node.next.keys():
cur_node = cur_node.next[c]
else:
return 0
return self.__sum(cur_node)
# 这里用到了递归
def __sum(self, node):
res = node.val # 这里不能初始化为 0
for c in node.next.keys():
res += self.__sum(node.next[c])
return res
# Your MapSum object will be instantiated and called as such:
# obj = MapSum()
# obj.insert(key,val)
# param_2 = obj.sum(prefix)