Skip to content

Commit a26fce0

Browse files
committed
feat: add solutions to lc problem: No.1948
No.1948.Delete Duplicate Folders in System
1 parent c10a2f1 commit a26fce0

File tree

7 files changed

+948
-8
lines changed

7 files changed

+948
-8
lines changed

solution/1900-1999/1948.Delete Duplicate Folders in System/README.md

Lines changed: 320 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,32 +122,348 @@ tags:
122122

123123
<!-- solution:start -->
124124

125-
### 方法一
125+
### 方法一:字典树 + DFS
126+
127+
我们可以使用字典树来存储文件夹的结构,字典树的每个节点数据如下:
128+
129+
- `children`:一个字典,键为子文件夹的名称,值为对应的子节点。
130+
- `deleted`:一个布尔值,表示该节点是否被标记为待删除。
131+
132+
我们将所有路径插入到字典树中,然后使用 DFS 遍历字典树,构建每个子树的字符串表示。对于每个子树,如果它的字符串表示已经存在于一个全局字典中,则将该节点和全局字典中的对应节点都标记为待删除。最后,再次使用 DFS 遍历字典树,将未被标记的节点的路径添加到结果列表中。
126133

127134
<!-- tabs:start -->
128135

129136
#### Python3
130137

131138
```python
132-
139+
class Trie:
140+
def __init__(self):
141+
self.children: Dict[str, "Trie"] = defaultdict(Trie)
142+
self.deleted: bool = False
143+
144+
145+
class Solution:
146+
def deleteDuplicateFolder(self, paths: List[List[str]]) -> List[List[str]]:
147+
root = Trie()
148+
for path in paths:
149+
cur = root
150+
for name in path:
151+
if cur.children[name] is None:
152+
cur.children[name] = Trie()
153+
cur = cur.children[name]
154+
155+
g: Dict[str, Trie] = {}
156+
157+
def dfs(node: Trie) -> str:
158+
if not node.children:
159+
return ""
160+
subs: List[str] = []
161+
for name, child in node.children.items():
162+
subs.append(f"{name}({dfs(child)})")
163+
s = "".join(sorted(subs))
164+
if s in g:
165+
node.deleted = g[s].deleted = True
166+
else:
167+
g[s] = node
168+
return s
169+
170+
def dfs2(node: Trie) -> None:
171+
if node.deleted:
172+
return
173+
if path:
174+
ans.append(path[:])
175+
for name, child in node.children.items():
176+
path.append(name)
177+
dfs2(child)
178+
path.pop()
179+
180+
dfs(root)
181+
ans: List[List[str]] = []
182+
path: List[str] = []
183+
dfs2(root)
184+
return ans
133185
```
134186

135187
#### Java
136188

137189
```java
138-
190+
class Trie {
191+
Map<String, Trie> children;
192+
boolean deleted;
193+
194+
public Trie() {
195+
children = new HashMap<>();
196+
deleted = false;
197+
}
198+
}
199+
200+
class Solution {
201+
public List<List<String>> deleteDuplicateFolder(List<List<String>> paths) {
202+
Trie root = new Trie();
203+
for (List<String> path : paths) {
204+
Trie cur = root;
205+
for (String name : path) {
206+
if (!cur.children.containsKey(name)) {
207+
cur.children.put(name, new Trie());
208+
}
209+
cur = cur.children.get(name);
210+
}
211+
}
212+
213+
Map<String, Trie> g = new HashMap<>();
214+
215+
var dfs = new Function<Trie, String>() {
216+
@Override
217+
public String apply(Trie node) {
218+
if (node.children.isEmpty()) {
219+
return "";
220+
}
221+
List<String> subs = new ArrayList<>();
222+
for (var entry : node.children.entrySet()) {
223+
subs.add(entry.getKey() + "(" + apply(entry.getValue()) + ")");
224+
}
225+
Collections.sort(subs);
226+
String s = String.join("", subs);
227+
if (g.containsKey(s)) {
228+
node.deleted = true;
229+
g.get(s).deleted = true;
230+
} else {
231+
g.put(s, node);
232+
}
233+
return s;
234+
}
235+
};
236+
237+
dfs.apply(root);
238+
239+
List<List<String>> ans = new ArrayList<>();
240+
List<String> path = new ArrayList<>();
241+
242+
var dfs2 = new Function<Trie, Void>() {
243+
@Override
244+
public Void apply(Trie node) {
245+
if (node.deleted) {
246+
return null;
247+
}
248+
if (!path.isEmpty()) {
249+
ans.add(new ArrayList<>(path));
250+
}
251+
for (Map.Entry<String, Trie> entry : node.children.entrySet()) {
252+
path.add(entry.getKey());
253+
apply(entry.getValue());
254+
path.remove(path.size() - 1);
255+
}
256+
return null;
257+
}
258+
};
259+
260+
dfs2.apply(root);
261+
262+
return ans;
263+
}
264+
}
139265
```
140266

141267
#### C++
142268

143269
```cpp
144-
270+
class Trie {
271+
public:
272+
unordered_map<string, Trie*> children;
273+
bool deleted = false;
274+
};
275+
276+
class Solution {
277+
public:
278+
vector<vector<string>> deleteDuplicateFolder(vector<vector<string>>& paths) {
279+
Trie* root = new Trie();
280+
281+
for (auto& path : paths) {
282+
Trie* cur = root;
283+
for (auto& name : path) {
284+
if (cur->children.find(name) == cur->children.end()) {
285+
cur->children[name] = new Trie();
286+
}
287+
cur = cur->children[name];
288+
}
289+
}
290+
291+
unordered_map<string, Trie*> g;
292+
293+
auto dfs = [&](this auto&& dfs, Trie* node) -> string {
294+
if (node->children.empty()) return "";
295+
296+
vector<string> subs;
297+
for (auto& child : node->children) {
298+
subs.push_back(child.first + "(" + dfs(child.second) + ")");
299+
}
300+
sort(subs.begin(), subs.end());
301+
string s = "";
302+
for (auto& sub : subs) s += sub;
303+
304+
if (g.contains(s)) {
305+
node->deleted = true;
306+
g[s]->deleted = true;
307+
} else {
308+
g[s] = node;
309+
}
310+
return s;
311+
};
312+
313+
dfs(root);
314+
315+
vector<vector<string>> ans;
316+
vector<string> path;
317+
318+
auto dfs2 = [&](this auto&& dfs2, Trie* node) -> void {
319+
if (node->deleted) return;
320+
if (!path.empty()) {
321+
ans.push_back(path);
322+
}
323+
for (auto& child : node->children) {
324+
path.push_back(child.first);
325+
dfs2(child.second);
326+
path.pop_back();
327+
}
328+
};
329+
330+
dfs2(root);
331+
332+
return ans;
333+
}
334+
};
145335
```
146336

147337
#### Go
148338

149339
```go
340+
type Trie struct {
341+
children map[string]*Trie
342+
deleted bool
343+
}
344+
345+
func NewTrie() *Trie {
346+
return &Trie{
347+
children: make(map[string]*Trie),
348+
}
349+
}
350+
351+
func deleteDuplicateFolder(paths [][]string) (ans [][]string) {
352+
root := NewTrie()
353+
for _, path := range paths {
354+
cur := root
355+
for _, name := range path {
356+
if _, exists := cur.children[name]; !exists {
357+
cur.children[name] = NewTrie()
358+
}
359+
cur = cur.children[name]
360+
}
361+
}
362+
363+
g := make(map[string]*Trie)
364+
365+
var dfs func(*Trie) string
366+
dfs = func(node *Trie) string {
367+
if len(node.children) == 0 {
368+
return ""
369+
}
370+
var subs []string
371+
for name, child := range node.children {
372+
subs = append(subs, name+"("+dfs(child)+")")
373+
}
374+
sort.Strings(subs)
375+
s := strings.Join(subs, "")
376+
if existingNode, exists := g[s]; exists {
377+
node.deleted = true
378+
existingNode.deleted = true
379+
} else {
380+
g[s] = node
381+
}
382+
return s
383+
}
384+
385+
var dfs2 func(*Trie, []string)
386+
dfs2 = func(node *Trie, path []string) {
387+
if node.deleted {
388+
return
389+
}
390+
if len(path) > 0 {
391+
ans = append(ans, append([]string{}, path...))
392+
}
393+
for name, child := range node.children {
394+
dfs2(child, append(path, name))
395+
}
396+
}
397+
398+
dfs(root)
399+
dfs2(root, []string{})
400+
return ans
401+
}
402+
```
150403

404+
#### TypeScript
405+
406+
```ts
407+
function deleteDuplicateFolder(paths: string[][]): string[][] {
408+
class Trie {
409+
children: { [key: string]: Trie } = {};
410+
deleted: boolean = false;
411+
}
412+
413+
const root = new Trie();
414+
415+
for (const path of paths) {
416+
let cur = root;
417+
for (const name of path) {
418+
if (!cur.children[name]) {
419+
cur.children[name] = new Trie();
420+
}
421+
cur = cur.children[name];
422+
}
423+
}
424+
425+
const g: { [key: string]: Trie } = {};
426+
427+
const dfs = (node: Trie): string => {
428+
if (Object.keys(node.children).length === 0) return '';
429+
430+
const subs: string[] = [];
431+
for (const [name, child] of Object.entries(node.children)) {
432+
subs.push(`${name}(${dfs(child)})`);
433+
}
434+
subs.sort();
435+
const s = subs.join('');
436+
437+
if (g[s]) {
438+
node.deleted = true;
439+
g[s].deleted = true;
440+
} else {
441+
g[s] = node;
442+
}
443+
return s;
444+
};
445+
446+
dfs(root);
447+
448+
const ans: string[][] = [];
449+
const path: string[] = [];
450+
451+
const dfs2 = (node: Trie): void => {
452+
if (node.deleted) return;
453+
if (path.length > 0) {
454+
ans.push([...path]);
455+
}
456+
for (const [name, child] of Object.entries(node.children)) {
457+
path.push(name);
458+
dfs2(child);
459+
path.pop();
460+
}
461+
};
462+
463+
dfs2(root);
464+
465+
return ans;
466+
}
151467
```
152468

153469
<!-- tabs:end -->

0 commit comments

Comments
 (0)