返回
算法进阶:Trie 模板的应用——LeetCode 677. 键值映射
后端
2023-12-31 08:35:20
LeetCode 677. 键值映射
题目
实现一个 MapSum 类,支持两个方法,insert 和 sum:
- insert(string key, int val):插入一个键值对 key、val。如果键 key 已经存在,那么原来的键值对将被覆盖。
- sum(string prefix):返回所有以 prefix 为前缀的键 key 的值的总和。
示例:
MapSum mapSum = new MapSum();
mapSum.insert("apple", 3);
int total = mapSum.sum("ap"); // return 3 (apple = 3)
mapSum.insert("app", 2);
total = mapSum.sum("ap"); // return 5 (apple + app = 3 + 2)
问题分析
本题需要解决的问题是如何存储和查询键值对,以及如何计算所有以某个前缀开头的键的值的总和。
解决方案
我们将使用 Trie 模板来存储键值对,并使用 DFS 算法来计算所有以某个前缀开头的键的值的总和。
1. Trie 模板
Trie,又称字典树,是一种树形数据结构,用于存储字符串。它具有以下特点:
- 每个结点代表一个字符。
- 根结点不包含字符。
- 从根结点到每个叶结点的路径表示一个字符串。
- 叶结点表示一个完整的字符串。
2. DFS 算法
DFS,又称深度优先搜索,是一种遍历树形数据结构的算法。它的基本思想是:
- 从根结点开始,依次访问其所有子结点。
- 当访问到叶结点时,对该叶结点进行处理。
- 然后回溯到该叶结点的父结点,继续访问其剩余的子结点。
3. 代码实现
class MapSum:
def __init__(self):
self.root = {}
self.score = {}
def insert(self, key: str, val: int) -> None:
node = self.root
for char in key:
if char not in node:
node[char] = {}
node = node[char]
node['#'] = val # 表示 key 已经插入完成,可以计算 score 了
self.score[key] = val # 将 key-val 存储在 score 中,便于快速查询
def sum(self, prefix: str) -> int:
node = self.root
total = 0
for char in prefix:
if char not in node:
return 0 # prefix 不存在,返回 0
node = node[char]
# 找到前缀 prefix 的最后一个结点
# 再使用 DFS 遍历所有以该结点为起点的子结点,计算 score
def dfs(node, cur):
nonlocal total
for char in node:
if char == '#': # 表示遇到一个 key
total += cur
else:
dfs(node[char], cur + char) # 继续往下遍历
dfs(node, prefix)
return total
总结
本题通过将 Trie 模板与 DFS 算法相结合,实现了一个 MapSum 类,支持两个方法,insert 和 sum。insert 方法用于插入键值对,sum 方法用于计算所有以某个前缀开头的键的值的总和。