Skip to content

Commit 63b75b6

Browse files
committed
Sync LeetCode submission Runtime - 174 ms (64.04%), Memory - 48.8 MB (67.42%)
1 parent f8406b0 commit 63b75b6

File tree

2 files changed

+135
-0
lines changed

2 files changed

+135
-0
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<p>Due to a bug, there are many duplicate folders in a file system. You are given a 2D array <code>paths</code>, where <code>paths[i]</code> is an array representing an absolute path to the <code>i<sup>th</sup></code> folder in the file system.</p>
2+
3+
<ul>
4+
<li>For example, <code>[&quot;one&quot;, &quot;two&quot;, &quot;three&quot;]</code> represents the path <code>&quot;/one/two/three&quot;</code>.</li>
5+
</ul>
6+
7+
<p>Two folders (not necessarily on the same level) are <strong>identical</strong> if they contain the <strong>same non-empty</strong> set of identical subfolders and underlying subfolder structure. The folders <strong>do not</strong> need to be at the root level to be identical. If two or more folders are <strong>identical</strong>, then <strong>mark</strong> the folders as well as all their subfolders.</p>
8+
9+
<ul>
10+
<li>For example, folders <code>&quot;/a&quot;</code> and <code>&quot;/b&quot;</code> in the file structure below are identical. They (as well as their subfolders) should <strong>all</strong> be marked:
11+
12+
<ul>
13+
<li><code>/a</code></li>
14+
<li><code>/a/x</code></li>
15+
<li><code>/a/x/y</code></li>
16+
<li><code>/a/z</code></li>
17+
<li><code>/b</code></li>
18+
<li><code>/b/x</code></li>
19+
<li><code>/b/x/y</code></li>
20+
<li><code>/b/z</code></li>
21+
</ul>
22+
</li>
23+
<li>However, if the file structure also included the path <code>&quot;/b/w&quot;</code>, then the folders <code>&quot;/a&quot;</code> and <code>&quot;/b&quot;</code> would not be identical. Note that <code>&quot;/a/x&quot;</code> and <code>&quot;/b/x&quot;</code> would still be considered identical even with the added folder.</li>
24+
</ul>
25+
26+
<p>Once all the identical folders and their subfolders have been marked, the file system will <strong>delete</strong> all of them. The file system only runs the deletion once, so any folders that become identical after the initial deletion are not deleted.</p>
27+
28+
<p>Return <em>the 2D array </em><code>ans</code> <em>containing the paths of the <strong>remaining</strong> folders after deleting all the marked folders. The paths may be returned in <strong>any</strong> order</em>.</p>
29+
30+
<p>&nbsp;</p>
31+
<p><strong class="example">Example 1:</strong></p>
32+
<img alt="" src="https://assets.leetcode.com/uploads/2021/07/19/lc-dupfolder1.jpg" style="width: 200px; height: 218px;" />
33+
<pre>
34+
<strong>Input:</strong> paths = [[&quot;a&quot;],[&quot;c&quot;],[&quot;d&quot;],[&quot;a&quot;,&quot;b&quot;],[&quot;c&quot;,&quot;b&quot;],[&quot;d&quot;,&quot;a&quot;]]
35+
<strong>Output:</strong> [[&quot;d&quot;],[&quot;d&quot;,&quot;a&quot;]]
36+
<strong>Explanation:</strong> The file structure is as shown.
37+
Folders &quot;/a&quot; and &quot;/c&quot; (and their subfolders) are marked for deletion because they both contain an empty
38+
folder named &quot;b&quot;.
39+
</pre>
40+
41+
<p><strong class="example">Example 2:</strong></p>
42+
<img alt="" src="https://assets.leetcode.com/uploads/2021/07/19/lc-dupfolder2.jpg" style="width: 200px; height: 355px;" />
43+
<pre>
44+
<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;]]
45+
<strong>Output:</strong> [[&quot;c&quot;],[&quot;c&quot;,&quot;b&quot;],[&quot;a&quot;],[&quot;a&quot;,&quot;b&quot;]]
46+
<strong>Explanation: </strong>The file structure is as shown.
47+
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;.
48+
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.
49+
</pre>
50+
51+
<p><strong class="example">Example 3:</strong></p>
52+
<img alt="" src="https://assets.leetcode.com/uploads/2021/07/19/lc-dupfolder3.jpg" style="width: 200px; height: 201px;" />
53+
<pre>
54+
<strong>Input:</strong> paths = [[&quot;a&quot;,&quot;b&quot;],[&quot;c&quot;,&quot;d&quot;],[&quot;c&quot;],[&quot;a&quot;]]
55+
<strong>Output:</strong> [[&quot;c&quot;],[&quot;c&quot;,&quot;d&quot;],[&quot;a&quot;],[&quot;a&quot;,&quot;b&quot;]]
56+
<strong>Explanation:</strong> All folders are unique in the file system.
57+
Note that the returned array can be in a different order as the order does not matter.
58+
</pre>
59+
60+
<p>&nbsp;</p>
61+
<p><strong>Constraints:</strong></p>
62+
63+
<ul>
64+
<li><code>1 &lt;= paths.length &lt;= 2 * 10<sup>4</sup></code></li>
65+
<li><code>1 &lt;= paths[i].length &lt;= 500</code></li>
66+
<li><code>1 &lt;= paths[i][j].length &lt;= 10</code></li>
67+
<li><code>1 &lt;= sum(paths[i][j].length) &lt;= 2 * 10<sup>5</sup></code></li>
68+
<li><code>path[i][j]</code> consists of lowercase English letters.</li>
69+
<li>No two paths lead to the same folder.</li>
70+
<li>For any folder not at the root level, its parent folder will also be in the input.</li>
71+
</ul>
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
class Trie:
2+
# current node structure's serialized representation
3+
serial: str = ""
4+
# current node's child nodes
5+
children: dict
6+
7+
def __init__(self):
8+
self.children = dict()
9+
10+
11+
class Solution:
12+
def deleteDuplicateFolder(self, paths: List[List[str]]) -> List[List[str]]:
13+
# root node
14+
root = Trie()
15+
16+
for path in paths:
17+
cur = root
18+
for node in path:
19+
if node not in cur.children:
20+
cur.children[node] = Trie()
21+
cur = cur.children[node]
22+
23+
# hash table records the occurrence times of each serialized representation
24+
freq = Counter()
25+
26+
# post-order traversal based on depth-first search, calculate the serialized representation of each node structure
27+
def construct(node: Trie) -> None:
28+
# if it is a leaf node, then the serialization is represented as an empty string, and no operation is required.
29+
if not node.children:
30+
return
31+
32+
v = list()
33+
# if it is not a leaf node, the serialization representation of the child node structure needs to be calculated first.
34+
for folder, child in node.children.items():
35+
construct(child)
36+
v.append(folder + "(" + child.serial + ")")
37+
38+
# to prevent issues with order, sorting is needed
39+
v.sort()
40+
node.serial = "".join(v)
41+
# add to hash table
42+
freq[node.serial] += 1
43+
44+
construct(root)
45+
46+
ans = list()
47+
# record the path from the root node to the current node.
48+
path = list()
49+
50+
def operate(node: Trie) -> None:
51+
# if the serialization appears more than once in the hash table, it needs to be deleted.
52+
if freq[node.serial] > 1:
53+
return
54+
# otherwise add the path to the answer
55+
if path:
56+
ans.append(path[:])
57+
58+
for folder, child in node.children.items():
59+
path.append(folder)
60+
operate(child)
61+
path.pop()
62+
63+
operate(root)
64+
return ans

0 commit comments

Comments
 (0)