Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit d369cf9

Browse files
feat: add solution for deleting duplicate folders in a file system (#4581)
1 parent c10a2f1 commit d369cf9

File tree

4 files changed

+367
-3
lines changed

4 files changed

+367
-3
lines changed

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

Lines changed: 122 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,58 @@ tags:
129129
#### Python3
130130

131131
```python
132-
132+
class TrieNode:
133+
def __init__(self):
134+
self.children = collections.defaultdict(TrieNode)
135+
self.key = ""
136+
self.deleted = False
137+
138+
139+
class Solution:
140+
def deleteDuplicateFolder(self, paths: List[List[str]]) -> List[List[str]]:
141+
root = TrieNode()
142+
143+
for path in paths:
144+
current = root
145+
for folder in path:
146+
current = current.children[folder]
147+
current.key = folder
148+
149+
seen = collections.defaultdict(list)
150+
151+
def dfs(node):
152+
if not node.children:
153+
return ""
154+
keys = []
155+
for key, child in node.children.items():
156+
serialized = dfs(child)
157+
keys.append(f"{key}({serialized})")
158+
keys.sort()
159+
serialized = "".join(keys)
160+
if len(seen[serialized]) > 0:
161+
for duplicate in seen[serialized]:
162+
duplicate.deleted = True
163+
node.deleted = True
164+
seen[serialized].append(node)
165+
return serialized
166+
167+
dfs(root)
168+
169+
result = []
170+
path = []
171+
172+
def collect(node):
173+
if node.deleted:
174+
return
175+
if path:
176+
result.append(path.copy())
177+
for key, child in node.children.items():
178+
path.append(key)
179+
collect(child)
180+
path.pop()
181+
182+
collect(root)
183+
return result
133184
```
134185

135186
#### Java
@@ -147,6 +198,76 @@ tags:
147198
#### Go
148199

149200
```go
201+
type TrieNode struct {
202+
children map[string]*TrieNode
203+
key string
204+
deleted bool
205+
}
206+
207+
func deleteDuplicateFolder(paths [][]string) [][]string {
208+
root := &TrieNode{children: make(map[string]*TrieNode)}
209+
210+
for _, path := range paths {
211+
current := root
212+
for _, folder := range path {
213+
if _, ok := current.children[folder]; !ok {
214+
current.children[folder] = &TrieNode{
215+
children: make(map[string]*TrieNode),
216+
key: folder,
217+
}
218+
}
219+
current = current.children[folder]
220+
}
221+
}
222+
223+
seen := make(map[string]*TrieNode)
224+
var dfs func(*TrieNode) string
225+
dfs = func(node *TrieNode) string {
226+
if node == nil || len(node.children) == 0 {
227+
return ""
228+
}
229+
230+
var keys []string
231+
for key, child := range node.children {
232+
serialized := dfs(child)
233+
keys = append(keys, key+"("+serialized+")")
234+
}
235+
sort.Strings(keys)
236+
serialized := strings.Join(keys, "")
237+
238+
if existing, ok := seen[serialized]; ok {
239+
existing.deleted = true
240+
node.deleted = true
241+
} else {
242+
seen[serialized] = node
243+
}
244+
245+
return serialized
246+
}
247+
dfs(root)
248+
249+
var result [][]string
250+
var path []string
251+
var collect func(*TrieNode)
252+
collect = func(node *TrieNode) {
253+
if node.deleted {
254+
return
255+
}
256+
if len(path) > 0 {
257+
newPath := make([]string, len(path))
258+
copy(newPath, path)
259+
result = append(result, newPath)
260+
}
261+
for key, child := range node.children {
262+
path = append(path, key)
263+
collect(child)
264+
path = path[:len(path)-1]
265+
}
266+
}
267+
collect(root)
268+
269+
return result
270+
}
150271

151272
```
152273

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

Lines changed: 123 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ folder named "b".
6868
<pre>
6969
<strong>Input:</strong> paths = [[&quot;a&quot;],[&quot;c&quot;],[&quot;a&quot;,&quot;b&quot;],[&quot;c&quot;,&quot;b&quot;],[&quot;a&quot;,&quot;b&quot;,&quot;x&quot;],[&quot;a&quot;,&quot;b&quot;,&quot;x&quot;,&quot;y&quot;],[&quot;w&quot;],[&quot;w&quot;,&quot;y&quot;]]
7070
<strong>Output:</strong> [[&quot;c&quot;],[&quot;c&quot;,&quot;b&quot;],[&quot;a&quot;],[&quot;a&quot;,&quot;b&quot;]]
71-
<strong>Explanation: </strong>The file structure is as shown.
71+
<strong>Explanation: </strong>The file structure is as shown.
7272
Folders &quot;/a/b/x&quot; and &quot;/w&quot; (and their subfolders) are marked for deletion because they both contain an empty folder named &quot;y&quot;.
7373
Note that folders &quot;/a&quot; and &quot;/c&quot; are identical after the deletion, but they are not deleted because they were not marked beforehand.
7474
</pre>
@@ -108,7 +108,58 @@ Note that the returned array can be in a different order as the order does not m
108108
#### Python3
109109

110110
```python
111-
111+
class TrieNode:
112+
def __init__(self):
113+
self.children = collections.defaultdict(TrieNode)
114+
self.key = ""
115+
self.deleted = False
116+
117+
118+
class Solution:
119+
def deleteDuplicateFolder(self, paths: List[List[str]]) -> List[List[str]]:
120+
root = TrieNode()
121+
122+
for path in paths:
123+
current = root
124+
for folder in path:
125+
current = current.children[folder]
126+
current.key = folder
127+
128+
seen = collections.defaultdict(list)
129+
130+
def dfs(node):
131+
if not node.children:
132+
return ""
133+
keys = []
134+
for key, child in node.children.items():
135+
serialized = dfs(child)
136+
keys.append(f"{key}({serialized})")
137+
keys.sort()
138+
serialized = "".join(keys)
139+
if len(seen[serialized]) > 0:
140+
for duplicate in seen[serialized]:
141+
duplicate.deleted = True
142+
node.deleted = True
143+
seen[serialized].append(node)
144+
return serialized
145+
146+
dfs(root)
147+
148+
result = []
149+
path = []
150+
151+
def collect(node):
152+
if node.deleted:
153+
return
154+
if path:
155+
result.append(path.copy())
156+
for key, child in node.children.items():
157+
path.append(key)
158+
collect(child)
159+
path.pop()
160+
161+
collect(root)
162+
return result
112163
```
113164

114165
#### Java
@@ -126,6 +177,76 @@ Note that the returned array can be in a different order as the order does not m
126177
#### Go
127178

128179
```go
180+
type TrieNode struct {
181+
children map[string]*TrieNode
182+
key string
183+
deleted bool
184+
}
185+
186+
func deleteDuplicateFolder(paths [][]string) [][]string {
187+
root := &TrieNode{children: make(map[string]*TrieNode)}
188+
189+
for _, path := range paths {
190+
current := root
191+
for _, folder := range path {
192+
if _, ok := current.children[folder]; !ok {
193+
current.children[folder] = &TrieNode{
194+
children: make(map[string]*TrieNode),
195+
key: folder,
196+
}
197+
}
198+
current = current.children[folder]
199+
}
200+
}
201+
202+
seen := make(map[string]*TrieNode)
203+
var dfs func(*TrieNode) string
204+
dfs = func(node *TrieNode) string {
205+
if node == nil || len(node.children) == 0 {
206+
return ""
207+
}
208+
209+
var keys []string
210+
for key, child := range node.children {
211+
serialized := dfs(child)
212+
keys = append(keys, key+"("+serialized+")")
213+
}
214+
sort.Strings(keys)
215+
serialized := strings.Join(keys, "")
216+
217+
if existing, ok := seen[serialized]; ok {
218+
existing.deleted = true
219+
node.deleted = true
220+
} else {
221+
seen[serialized] = node
222+
}
223+
224+
return serialized
225+
}
226+
dfs(root)
227+
228+
var result [][]string
229+
var path []string
230+
var collect func(*TrieNode)
231+
collect = func(node *TrieNode) {
232+
if node.deleted {
233+
return
234+
}
235+
if len(path) > 0 {
236+
newPath := make([]string, len(path))
237+
copy(newPath, path)
238+
result = append(result, newPath)
239+
}
240+
for key, child := range node.children {
241+
path = append(path, key)
242+
collect(child)
243+
path = path[:len(path)-1]
244+
}
245+
}
246+
collect(root)
247+
248+
return result
249+
}
129250

130251
```
131252

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
type TrieNode struct {
2+
children map[string]*TrieNode
3+
key string
4+
deleted bool
5+
}
6+
7+
func deleteDuplicateFolder(paths [][]string) [][]string {
8+
root := &TrieNode{children: make(map[string]*TrieNode)}
9+
10+
for _, path := range paths {
11+
current := root
12+
for _, folder := range path {
13+
if _, ok := current.children[folder]; !ok {
14+
current.children[folder] = &TrieNode{
15+
children: make(map[string]*TrieNode),
16+
key: folder,
17+
}
18+
}
19+
current = current.children[folder]
20+
}
21+
}
22+
23+
seen := make(map[string]*TrieNode)
24+
var dfs func(*TrieNode) string
25+
dfs = func(node *TrieNode) string {
26+
if node == nil || len(node.children) == 0 {
27+
return ""
28+
}
29+
30+
var keys []string
31+
for key, child := range node.children {
32+
serialized := dfs(child)
33+
keys = append(keys, key+"("+serialized+")")
34+
}
35+
sort.Strings(keys)
36+
serialized := strings.Join(keys, "")
37+
38+
if existing, ok := seen[serialized]; ok {
39+
existing.deleted = true
40+
node.deleted = true
41+
} else {
42+
seen[serialized] = node
43+
}
44+
45+
return serialized
46+
}
47+
dfs(root)
48+
49+
var result [][]string
50+
var path []string
51+
var collect func(*TrieNode)
52+
collect = func(node *TrieNode) {
53+
if node.deleted {
54+
return
55+
}
56+
if len(path) > 0 {
57+
newPath := make([]string, len(path))
58+
copy(newPath, path)
59+
result = append(result, newPath)
60+
}
61+
for key, child := range node.children {
62+
path = append(path, key)
63+
collect(child)
64+
path = path[:len(path)-1]
65+
}
66+
}
67+
collect(root)
68+
69+
return result
70+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /