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 b767f36

Browse files
committed
feat: add solutions to lc problem: No.1233
No.1233.Remove Sub-Folders from the Filesystem
1 parent eb1ff32 commit b767f36

File tree

6 files changed

+405
-235
lines changed

6 files changed

+405
-235
lines changed

‎solution/1200-1299/1233.Remove Sub-Folders from the Filesystem/README.md‎

Lines changed: 181 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -56,110 +56,245 @@
5656

5757
<!-- 这里可写通用的实现逻辑 -->
5858

59-
**方法一:排序 + 前缀树**
59+
**方法一:排序**
60+
61+
我们先将数组 `folder` 按照字典序排序,然后遍历数组,对于当前遍历到的文件夹 $f,ドル如果它的长度大于等于答案数组中最后一个文件夹的长度,并且它的前缀包含答案数组的最后一个文件夹再加上一个 `/`,则说明 $f$ 是答案数组中最后一个文件夹的子文件夹,我们不需要将其加入答案数组中。否则,我们将 $f$ 加入答案数组中。
62+
63+
遍历结束后,答案数组中的文件夹即为题目要求的答案。
64+
65+
时间复杂度 $O(n \times \log n \times m),ドル空间复杂度 $O(m)$。其中 $n$ 和 $m$ 分别为数组 `folder` 的长度和数组 `folder` 中字符串的最大长度。
66+
67+
**方法二:字典树**
68+
69+
我们可以使用字典树存储数组 `folder` 中的所有文件夹。字典树的每个节点包含 `children` 字段,用于存储当前节点的子节点,以及 `fid` 字段,用于存储当前节点对应的文件夹在数组 `folder` 中的下标。
70+
71+
对于数组 `folder` 中的每个文件夹 $f,ドル我们先将 $f$ 按照 `/` 分割成若干个子串,然后从根节点开始,依次将子串加入字典树中。接下来,我们从根节点开始搜索字典树,如果当前节点的 `fid` 字段不为 `-1`,则说明当前节点对应的文件夹是答案数组中的一个文件夹,我们将其加入答案数组并且返回。否则,我们递归地搜索当前节点的所有子节点,最终返回答案数组。
72+
73+
时间复杂度 $O(n \times m),ドル空间复杂度 $O(n \times m)$。其中 $n$ 和 $m$ 分别为数组 `folder` 的长度和数组 `folder` 中字符串的最大长度。
6074

6175
<!-- tabs:start -->
6276

6377
### **Python3**
6478

6579
<!-- 这里可写当前语言的特殊实现逻辑 -->
6680

81+
```python
82+
class Solution:
83+
def removeSubfolders(self, folder: List[str]) -> List[str]:
84+
folder.sort()
85+
ans = [folder[0]]
86+
for f in folder[1:]:
87+
m, n = len(ans[-1]), len(f)
88+
if m >= n or not (ans[-1] == f[:m] and f[m] == '/'):
89+
ans.append(f)
90+
return ans
91+
```
92+
6793
```python
6894
class Trie:
6995
def __init__(self):
7096
self.children = {}
71-
self.is_end = False
97+
self.fid = -1
7298

73-
def insert(self, w):
99+
def insert(self, i, f):
74100
node = self
75-
ps = w.split('/')
101+
ps = f.split('/')
76102
for p in ps[1:]:
77103
if p not in node.children:
78104
node.children[p] = Trie()
79105
node = node.children[p]
80-
node.is_end = True
106+
node.fid = i
81107

82-
def search(self, w):
83-
node = self
84-
ps = w.split('/')
85-
for p in ps[1:]:
86-
if p not in node.children:
87-
return False
88-
node = node.children[p]
89-
if node.is_end:
90-
return True
91-
return False
108+
def search(self):
109+
def dfs(root):
110+
if root.fid != -1:
111+
ans.append(root.fid)
112+
return
113+
for child in root.children.values():
114+
dfs(child)
92115

116+
ans = []
117+
dfs(self)
118+
return ans
93119

94120
class Solution:
95121
def removeSubfolders(self, folder: List[str]) -> List[str]:
96122
trie = Trie()
97-
folder.sort(key=lambda x: len(x.split('/')))
98-
ans = []
99-
for v in folder:
100-
if not trie.search(v):
101-
trie.insert(v)
102-
ans.append(v)
103-
return ans
123+
for i, f in enumerate(folder):
124+
trie.insert(i, f)
125+
return [folder[i] for i in trie.search()]
104126
```
105127

106128
### **Java**
107129

108130
<!-- 这里可写当前语言的特殊实现逻辑 -->
109131

132+
```java
133+
class Solution {
134+
public List<String> removeSubfolders(String[] folder) {
135+
Arrays.sort(folder);
136+
List<String> ans = new ArrayList<>();
137+
ans.add(folder[0]);
138+
for (int i = 1; i < folder.length; ++i) {
139+
int m = ans.get(ans.size() - 1).length();
140+
int n = folder[i].length();
141+
if (m >= n || !(ans.get(ans.size() - 1).equals(folder[i].substring(0, m)) && folder[i].charAt(m) == '/')) {
142+
ans.add(folder[i]);
143+
}
144+
}
145+
return ans;
146+
}
147+
}
148+
```
149+
110150
```java
111151
class Trie {
112-
Map<String, Trie> children = new HashMap<>();
113-
boolean isEnd;
152+
privateMap<String, Trie> children = new HashMap<>();
153+
privateint fid =-1;
114154

115-
void insert(String w) {
155+
publicvoid insert(intfid, String f) {
116156
Trie node = this;
117-
String[] ps = w.split("/");
157+
String[] ps = f.split("/");
118158
for (int i = 1; i < ps.length; ++i) {
119159
String p = ps[i];
120160
if (!node.children.containsKey(p)) {
121161
node.children.put(p, new Trie());
122162
}
123163
node = node.children.get(p);
124164
}
125-
node.isEnd = true;
165+
node.fid = fid;
126166
}
127167

128-
boolean search(String w) {
129-
Trie node = this;
130-
String[] ps = w.split("/");
131-
for (int i = 1; i < ps.length; ++i) {
132-
String p = ps[i];
133-
if (!node.children.containsKey(p)) {
134-
return false;
135-
}
136-
node = node.children.get(p);
137-
if (node.isEnd) {
138-
return true;
139-
}
168+
public List<Integer> search() {
169+
List<Integer> ans = new ArrayList<>();
170+
dfs(this, ans);
171+
return ans;
172+
}
173+
174+
private void dfs(Trie root, List<Integer> ans) {
175+
if (root.fid != -1) {
176+
ans.add(root.fid);
177+
return;
178+
}
179+
for (var child : root.children.values()) {
180+
dfs(child, ans);
140181
}
141-
return false;
142182
}
143183
}
144184

145185
class Solution {
146186
public List<String> removeSubfolders(String[] folder) {
147-
Arrays.sort(folder, (a, b) -> a.split("/").length - b.split("/").length);
148187
Trie trie = new Trie();
188+
for (int i = 0; i < folder.length; ++i) {
189+
trie.insert(i, folder[i]);
190+
}
149191
List<String> ans = new ArrayList<>();
150-
for (String v : folder) {
151-
if (!trie.search(v)) {
152-
trie.insert(v);
153-
ans.add(v);
154-
}
192+
for (int i : trie.search()) {
193+
ans.add(folder[i]);
155194
}
156195
return ans;
157196
}
158197
}
159198
```
160199

200+
### **C++**
201+
202+
```cpp
203+
class Solution {
204+
public:
205+
vector<string> removeSubfolders(vector<string>& folder) {
206+
sort(folder.begin(), folder.end());
207+
vector<string> ans = {folder[0]};
208+
for (int i = 1; i < folder.size(); ++i) {
209+
int m = ans.back().size();
210+
int n = folder[i].size();
211+
if (m >= n || !(ans.back() == folder[i].substr(0, m) && folder[i][m] == '/')) {
212+
ans.emplace_back(folder[i]);
213+
}
214+
}
215+
return ans;
216+
}
217+
};
218+
```
219+
220+
```cpp
221+
class Trie {
222+
public:
223+
void insert(int fid, string& f) {
224+
Trie* node = this;
225+
vector<string> ps = split(f, '/');
226+
for (int i = 1; i < ps.size(); ++i) {
227+
auto& p = ps[i];
228+
if (!node->children.count(p)) {
229+
node->children[p] = new Trie();
230+
}
231+
node = node->children[p];
232+
}
233+
node->fid = fid;
234+
}
235+
236+
vector<int> search() {
237+
vector<int> ans;
238+
function<void(Trie*)> dfs = [&](Trie* root) {
239+
if (root->fid != -1) {
240+
ans.push_back(root->fid);
241+
return;
242+
}
243+
for (auto& [_, child] : root->children) {
244+
dfs(child);
245+
}
246+
};
247+
dfs(this);
248+
return ans;
249+
}
250+
251+
vector<string> split(string& s, char delim) {
252+
stringstream ss(s);
253+
string item;
254+
vector<string> res;
255+
while (getline(ss, item, delim)) {
256+
res.emplace_back(item);
257+
}
258+
return res;
259+
}
260+
261+
private:
262+
unordered_map<string, Trie*> children;
263+
int fid = -1;
264+
};
265+
266+
class Solution {
267+
public:
268+
vector<string> removeSubfolders(vector<string>& folder) {
269+
Trie* trie = new Trie();
270+
for (int i = 0; i < folder.size(); ++i) {
271+
trie->insert(i, folder[i]);
272+
}
273+
vector<string> ans;
274+
for (int i : trie->search()) {
275+
ans.emplace_back(folder[i]);
276+
}
277+
return ans;
278+
}
279+
};
280+
```
281+
161282
### **Go**
162283

284+
```go
285+
func removeSubfolders(folder []string) []string {
286+
sort.Strings(folder)
287+
ans := []string{folder[0]}
288+
for _, f := range folder[1:] {
289+
m, n := len(ans[len(ans)-1]), len(f)
290+
if m >= n || !(ans[len(ans)-1] == f[:m] && f[m] == '/') {
291+
ans = append(ans, f)
292+
}
293+
}
294+
return ans
295+
}
296+
```
297+
163298
```go
164299
type Trie struct {
165300
children map[string]*Trie

0 commit comments

Comments
(0)

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