forked from kamyu104/LeetCode-Solutions
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdelete-duplicate-folders-in-system.py
102 lines (91 loc) · 3.58 KB
/
delete-duplicate-folders-in-system.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# Time: O(n * m * l + tlogt + l * t), m is the max number of folders in a path,
# , n is the number of paths
# , l is the max length of folder name
# , t is the size of trie
# Space: O(l * t)
import collections
class Solution(object):
def deleteDuplicateFolder(self, paths):
"""
:type paths: List[List[str]]
:rtype: List[List[str]]
"""
def mark(node, lookup, node_ids):
id_pairs = []
for subfolder_id, child in node.iteritems():
if child == "_del":
continue
id_pairs.append((subfolder_id, mark(child, lookup, node_ids)))
id_pairs.sort()
node_id = node_ids[tuple(id_pairs)]
if node_id:
if node_id in lookup:
lookup[node_id]["_del"]
node["_del"]
else:
lookup[node_id] = node
return node_id
def sweep(node, id_folders, path, result):
if path:
result.append([id_folders[i] for i in path])
for subfolder_id, child in node.iteritems():
if "_del" in child:
continue
path.append(subfolder_id)
sweep(child, id_folders, path, result)
path.pop()
_trie = lambda: collections.defaultdict(_trie)
trie = _trie()
folder_ids = collections.defaultdict()
folder_ids.default_factory = folder_ids.__len__
id_folders = {}
for path in paths:
node = trie
for folder in path:
if folder_ids[folder] not in id_folders:
id_folders[folder_ids[folder]] = folder
node = node[folder_ids[folder]]
node_ids = collections.defaultdict()
node_ids.default_factory = node_ids.__len__
mark(trie, {}, node_ids)
result = []
sweep(trie, id_folders, [], result)
return result
# Time: O(n * m * l + l * tlogt + l * t^2), m is the max number of folders in a path,
# , n is the number of paths
# , l is the max length of folder name
# , t is the size of trie
# Space: O(l * t^2)
import collections
class Solution2(object):
def deleteDuplicateFolder(self, paths):
"""
:type paths: List[List[str]]
:rtype: List[List[str]]
"""
def mark(node, lookup):
serialized_tree = "(" + "".join(subfolder + mark(child, lookup) for subfolder, child in sorted(node.iteritems()) if child != "_del") + ")"
if serialized_tree != "()":
if serialized_tree in lookup:
lookup[serialized_tree]["_del"]
node["_del"]
else:
lookup[serialized_tree] = node
return serialized_tree
def sweep(node, path, result):
if path:
result.append(path[:])
for subfolder, child in node.iteritems():
if "_del" in child:
continue
path.append(subfolder)
sweep(child, path, result)
path.pop()
_trie = lambda: collections.defaultdict(_trie)
trie = _trie()
for path in paths:
reduce(dict.__getitem__, path, trie)
mark(trie, {})
result = []
sweep(trie, [], result)
return result