Skip to content

Commit 3dc6198

Browse files
committed
feat: add solutions to lc problem: No.0677
No.0677.Map Sum Pairs
1 parent 4b4b637 commit 3dc6198

File tree

8 files changed

+643
-150
lines changed

8 files changed

+643
-150
lines changed

solution/0600-0699/0675.Cut Off Trees for Golf Event/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@
6363

6464
<!-- 这里可写通用的实现逻辑 -->
6565

66-
题目的一个关键信息是“所有树的高度都不同”,要按照从小到大的顺序依次砍树,因此,先遍历树林,找出所有树及对应的坐标点。然后将树按照高度升序排列。
66+
**方法一:BFS + 优先队列(A\* 算法)**
67+
68+
题目的一个关键信息是“所有树的高度都不同”,要按照从小到大的顺序依次砍树,因此,我们先遍历树林,找出所有树及对应的坐标点。然后将树按照高度升序排列。
6769

6870
接下来就是找相邻两个点之间的最短距离。可以用 BFS,A\* 算法优化搜索。
6971

solution/0600-0699/0677.Map Sum Pairs/README.md

Lines changed: 223 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,20 @@ mapSum.sum("ap"); // 返回 5 (<u>ap</u>ple + <u>ap</u>p = 3 + 2 = 5)
5555

5656
<!-- 这里可写通用的实现逻辑 -->
5757

58-
利用哈希表存储每个键的所有前缀子串。
58+
**方法一:哈希表 + 前缀树**
59+
60+
我们用哈希表 $d$ 存放键值对,用前缀树 $t$ 存放键值对的前缀和。前缀树的每个节点包含两个信息:
61+
62+
- `val`:以该节点为前缀的键值对的值的总和
63+
- `children`:长度为 $26$ 的数组,存放该节点的子节点
64+
65+
插入键值对 $(key, val)$ 时,我们先判断哈希表是否存在该键,如果存在,那么前缀树每个节点的 `val` 都要减去该键原来的值,然后再加上新的值。如果不存在,那么前缀树每个节点的 `val` 都要加上新的值。
66+
67+
查询前缀和时,我们从前缀树的根节点开始,遍历前缀字符串,如果当前节点的子节点中不存在该字符,那么说明前缀树中不存在该前缀,返回 $0$。否则,继续遍历下一个字符,直到遍历完前缀字符串,返回当前节点的 `val`
68+
69+
时间复杂度方面,插入键值对的时间复杂度为 $O(n)$,其中 $n$ 为键的长度。查询前缀和的时间复杂度为 $O(m)$,其中 $m$ 为前缀的长度。
70+
71+
空间复杂度 $O(n \times m \times C)$,其中 $n$ 和 $m$ 分别是键的数量以及键的最大长度;而 $C$ 是字符集的大小,本题中 $C = 26$。
5972

6073
<!-- tabs:start -->
6174

@@ -64,23 +77,43 @@ mapSum.sum("ap"); // 返回 5 (<u>ap</u>ple + <u>ap</u>p = 3 + 2 = 5)
6477
<!-- 这里可写当前语言的特殊实现逻辑 -->
6578

6679
```python
80+
class Trie:
81+
def __init__(self):
82+
self.children: List[Trie | None] = [None] * 26
83+
self.val: int = 0
84+
85+
def insert(self, w: str, x: int):
86+
node = self
87+
for c in w:
88+
idx = ord(c) - ord('a')
89+
if node.children[idx] is None:
90+
node.children[idx] = Trie()
91+
node = node.children[idx]
92+
node.val += x
93+
94+
def search(self, w: str) -> int:
95+
node = self
96+
for c in w:
97+
idx = ord(c) - ord('a')
98+
if node.children[idx] is None:
99+
return 0
100+
node = node.children[idx]
101+
return node.val
102+
103+
67104
class MapSum:
105+
68106
def __init__(self):
69-
"""
70-
Initialize your data structure here.
71-
"""
72-
self.data = defaultdict(int)
73-
self.t = defaultdict(int)
107+
self.d = defaultdict(int)
108+
self.tree = Trie()
74109

75110
def insert(self, key: str, val: int) -> None:
76-
old = self.t[key]
77-
self.t[key] = val
78-
for i in range(1, len(key) + 1):
79-
self.data[key[:i]] += val - old
111+
x = val - self.d[key]
112+
self.d[key] = val
113+
self.tree.insert(key, x)
80114

81115
def sum(self, prefix: str) -> int:
82-
return self.data[prefix]
83-
116+
return self.tree.search(prefix)
84117

85118
# Your MapSum object will be instantiated and called as such:
86119
# obj = MapSum()
@@ -93,27 +126,52 @@ class MapSum:
93126
<!-- 这里可写当前语言的特殊实现逻辑 -->
94127

95128
```java
129+
class Trie {
130+
private Trie[] children = new Trie[26];
131+
private int val;
132+
133+
public void insert(String w, int x) {
134+
Trie node = this;
135+
for (int i = 0; i < w.length(); ++i) {
136+
int idx = w.charAt(i) - 'a';
137+
if (node.children[idx] == null) {
138+
node.children[idx] = new Trie();
139+
}
140+
node = node.children[idx];
141+
node.val += x;
142+
}
143+
}
144+
145+
public int search(String w) {
146+
Trie node = this;
147+
for (int i = 0; i < w.length(); ++i) {
148+
int idx = w.charAt(i) - 'a';
149+
if (node.children[idx] == null) {
150+
return 0;
151+
}
152+
node = node.children[idx];
153+
}
154+
return node.val;
155+
}
156+
}
157+
96158
class MapSum {
97-
private Map<String, Integer> data;
98-
private Map<String, Integer> t;
159+
private Map<String, Integer> d = new HashMap<>();
160+
private Trie trie = new Trie();
161+
99162

100-
/** Initialize your data structure here. */
101163
public MapSum() {
102-
data = new HashMap<>();
103-
t = new HashMap<>();
164+
104165
}
105166

106167
public void insert(String key, int val) {
107-
int old = t.getOrDefault(key, 0);
108-
t.put(key, val);
109-
for (int i = 1; i < key.length() + 1; ++i) {
110-
String k = key.substring(0, i);
111-
data.put(k, data.getOrDefault(k, 0) + (val - old));
112-
}
168+
int x = val - d.getOrDefault(key, 0);
169+
d.put(key, val);
170+
trie.insert(key, x);
113171
}
114172

115173
public int sum(String prefix) {
116-
return data.getOrDefault(prefix, 0);
174+
return trie.search(prefix);
117175
}
118176
}
119177

@@ -128,27 +186,59 @@ class MapSum {
128186
### **C++**
129187

130188
```cpp
131-
class MapSum {
189+
class Trie {
132190
public:
133-
unordered_map<string, int> data;
134-
unordered_map<string, int> t;
191+
Trie()
192+
: children(26, nullptr) {
193+
}
135194

136-
/** Initialize your data structure here. */
195+
void insert(string& w, int x) {
196+
Trie* node = this;
197+
for (char c : w) {
198+
c -= 'a';
199+
if (!node->children[c]) {
200+
node->children[c] = new Trie();
201+
}
202+
node = node->children[c];
203+
node->val += x;
204+
}
205+
}
206+
207+
int search(string& w) {
208+
Trie* node = this;
209+
for (char c : w) {
210+
c -= 'a';
211+
if (!node->children[c]) {
212+
return 0;
213+
}
214+
node = node->children[c];
215+
}
216+
return node->val;
217+
}
218+
219+
private:
220+
vector<Trie*> children;
221+
int val = 0;
222+
};
223+
224+
class MapSum {
225+
public:
137226
MapSum() {
138227
}
139228

140229
void insert(string key, int val) {
141-
int old = t[key];
142-
t[key] = val;
143-
for (int i = 1; i < key.size() + 1; ++i) {
144-
string k = key.substr(0, i);
145-
data[k] += (val - old);
146-
}
230+
int x = val - d[key];
231+
d[key] = val;
232+
trie->insert(key, x);
147233
}
148234

149235
int sum(string prefix) {
150-
return data[prefix];
236+
return trie->search(prefix);
151237
}
238+
239+
private:
240+
unordered_map<string, int> d;
241+
Trie* trie = new Trie();
152242
};
153243

154244
/**
@@ -162,30 +252,50 @@ public:
162252
### **Go**
163253
164254
```go
255+
type trie struct {
256+
children [26]*trie
257+
val int
258+
}
259+
260+
func (t *trie) insert(w string, x int) {
261+
for _, c := range w {
262+
c -= 'a'
263+
if t.children[c] == nil {
264+
t.children[c] = &trie{}
265+
}
266+
t = t.children[c]
267+
t.val += x
268+
}
269+
}
270+
271+
func (t *trie) search(w string) int {
272+
for _, c := range w {
273+
c -= 'a'
274+
if t.children[c] == nil {
275+
return 0
276+
}
277+
t = t.children[c]
278+
}
279+
return t.val
280+
}
281+
165282
type MapSum struct {
166-
data map[string]int
167-
t map[string]int
283+
d map[string]int
284+
t *trie
168285
}
169286
170-
/** Initialize your data structure here. */
171287
func Constructor() MapSum {
172-
return MapSum{
173-
data: make(map[string]int),
174-
t: make(map[string]int),
175-
}
288+
return MapSum{make(map[string]int), &trie{}}
176289
}
177290
178291
func (this *MapSum) Insert(key string, val int) {
179-
old := this.t[key]
180-
this.t[key] = val
181-
for i := 1; i < len(key)+1; i++ {
182-
k := key[:i]
183-
this.data[k] += (val - old)
184-
}
292+
x := val - this.d[key]
293+
this.d[key] = val
294+
this.t.insert(key, x)
185295
}
186296
187297
func (this *MapSum) Sum(prefix string) int {
188-
return this.data[prefix]
298+
return this.t.search(prefix)
189299
}
190300
191301
/**
@@ -196,6 +306,70 @@ func (this *MapSum) Sum(prefix string) int {
196306
*/
197307
```
198308

309+
### **TypeScript**
310+
311+
```ts
312+
class Trie {
313+
children: Trie[];
314+
val: number;
315+
316+
constructor() {
317+
this.children = new Array(26);
318+
this.val = 0;
319+
}
320+
321+
insert(w: string, x: number) {
322+
let node: Trie = this;
323+
for (const c of w) {
324+
const i = c.charCodeAt(0) - 97;
325+
if (!node.children[i]) {
326+
node.children[i] = new Trie();
327+
}
328+
node = node.children[i];
329+
node.val += x;
330+
}
331+
}
332+
333+
search(w: string): number {
334+
let node: Trie = this;
335+
for (const c of w) {
336+
const i = c.charCodeAt(0) - 97;
337+
if (!node.children[i]) {
338+
return 0;
339+
}
340+
node = node.children[i];
341+
}
342+
return node.val;
343+
}
344+
}
345+
346+
class MapSum {
347+
d: Map<string, number>;
348+
t: Trie;
349+
constructor() {
350+
this.d = new Map();
351+
this.t = new Trie();
352+
}
353+
354+
insert(key: string, val: number): void {
355+
const x = val - (this.d.get(key) ?? 0);
356+
this.d.set(key, val);
357+
this.t.insert(key, x);
358+
}
359+
360+
sum(prefix: string): number {
361+
return this.t.search(prefix);
362+
}
363+
}
364+
365+
/**
366+
* Your MapSum object will be instantiated and called as such:
367+
* var obj = new MapSum()
368+
* obj.insert(key,val)
369+
* var param_2 = obj.sum(prefix)
370+
*/
371+
```
372+
199373
### **...**
200374

201375
```

0 commit comments

Comments
 (0)