Skip to content

Commit f96675d

Browse files
feat: Add Solution.java
1 parent 5637a97 commit f96675d

File tree

1 file changed

+117
-0
lines changed
  • solution/1900-1999/1948.Delete Duplicate Folders in System

1 file changed

+117
-0
lines changed
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import java.util.*;
2+
3+
class TrieNode {
4+
Map<String, TrieNode> children;
5+
Integer id;
6+
7+
public TrieNode() {
8+
this.children = new HashMap<>();
9+
this.id = null;
10+
}
11+
}
12+
13+
public class Solution {
14+
public List<List<String>> deleteDuplicateFolder(List<List<String>> paths) {
15+
TrieNode root = new TrieNode();
16+
17+
// Step 1: Build Trie (Tree)
18+
for (List<String> path : paths) {
19+
TrieNode node = root;
20+
for (String folder : path) {
21+
node = node.children.computeIfAbsent(folder, k -> new TrieNode());
22+
}
23+
}
24+
25+
// Step 2: Assign unique IDs to subtrees
26+
Map<String, List<TrieNode>> subtreeMap = new HashMap<>();
27+
28+
getSubtreeId(root, subtreeMap);
29+
30+
// Step 3: Mark duplicates
31+
Set<TrieNode> duplicates = new HashSet<>();
32+
for (List<TrieNode> nodes : subtreeMap.values()) {
33+
if (nodes.size() > 1) { // If more than one node has the same structure, mark as duplicate
34+
duplicates.addAll(nodes);
35+
}
36+
}
37+
38+
// Step 4: Collect remaining paths
39+
List<List<String>> ans = new ArrayList<>();
40+
collectRemainingPaths(root, new ArrayList<>(), duplicates, ans);
41+
42+
return ans;
43+
}
44+
45+
private String getSubtreeId(TrieNode node, Map<String, List<TrieNode>> subtreeMap) {
46+
if (node.children.isEmpty()) {
47+
return ""; // Empty subtree has no ID
48+
}
49+
50+
// Sort children lexicographically and form a string representing the subtree
51+
List<String> subtreeList = new ArrayList<>();
52+
for (Map.Entry<String, TrieNode> entry : node.children.entrySet()) {
53+
String folder = entry.getKey();
54+
TrieNode child = entry.getValue();
55+
subtreeList.add(folder + "(" + getSubtreeId(child, subtreeMap) + ")");
56+
}
57+
Collections.sort(subtreeList);
58+
59+
// Create a unique string representation of the subtree
60+
String subtree = String.join(",", subtreeList);
61+
62+
// Map the subtree representation to the node
63+
subtreeMap.computeIfAbsent(subtree, k -> new ArrayList<>()).add(node);
64+
65+
return subtree;
66+
}
67+
68+
private void collectRemainingPaths(TrieNode node, List<String> path, Set<TrieNode> duplicates, List<List<String>> ans) {
69+
if (duplicates.contains(node)) {
70+
return; // Skip this subtree because it is marked for deletion
71+
}
72+
73+
if (!path.isEmpty()) {
74+
ans.add(new ArrayList<>(path));
75+
}
76+
77+
for (Map.Entry<String, TrieNode> entry : node.children.entrySet()) {
78+
path.add(entry.getKey());
79+
collectRemainingPaths(entry.getValue(), path, duplicates, ans);
80+
path.remove(path.size() - 1);
81+
}
82+
}
83+
84+
public static void main(String[] args) {
85+
Solution sol = new Solution();
86+
87+
List<List<String>> paths1 = Arrays.asList(
88+
Arrays.asList("a"),
89+
Arrays.asList("c"),
90+
Arrays.asList("d"),
91+
Arrays.asList("a", "b"),
92+
Arrays.asList("c", "b"),
93+
Arrays.asList("d", "a")
94+
);
95+
96+
List<List<String>> result1 = sol.deleteDuplicateFolder(paths1);
97+
for (List<String> path : result1) {
98+
System.out.println(path);
99+
}
100+
101+
List<List<String>> paths2 = Arrays.asList(
102+
Arrays.asList("a"),
103+
Arrays.asList("c"),
104+
Arrays.asList("a", "b"),
105+
Arrays.asList("c", "b"),
106+
Arrays.asList("a", "b", "x"),
107+
Arrays.asList("a", "b", "x", "y"),
108+
Arrays.asList("w"),
109+
Arrays.asList("w", "y")
110+
);
111+
112+
List<List<String>> result2 = sol.deleteDuplicateFolder(paths2);
113+
for (List<String> path : result2) {
114+
System.out.println(path);
115+
}
116+
}
117+
}

0 commit comments

Comments
 (0)