Given a list of folders folder, return the folders after removing all sub-folders in those folders. You may return the answer in any order.
If a folder[i] is located within another folder[j], it is called a sub-folder of it.
The format of a path is one or more concatenated strings of the form: ‘/’ followed by one or more lowercase English letters.
For example, “/leetcode” and “/leetcode/problems” are valid paths while an empty string and “/” are not.
Example 1:
Input: folder = [“/a”,“/a/b”,“/c/d”,“/c/d/e”,“/c/f”]
Output: [“/a”,“/c/d”,“/c/f”]
Explanation: Folders “/a/b” is a subfolder of “/a” and “/c/d/e” is inside of folder “/c/d” in our filesystem.
Example 2:
Input: folder = [“/a”,“/a/b/c”,“/a/b/d”]
Output: [“/a”]
Explanation: Folders “/a/b/c” and “/a/b/d” will be removed because they are subfolders of “/a”.
Example 3:
Input: folder = [“/a/b/c”,“/a/b/ca”,“/a/b/d”]
Output: [“/a/b/c”,“/a/b/ca”,“/a/b/d”]
Constraints:
想了想, 还是得做道题。
这题其实就是找当前路径的所有父路径是不是同样在所给的 folder 中出现过, 我是采用类似与 Trie 的形式进行表达的, 每次添加新的路径都从根上进行添加, 节点的属性中有一个 is_shortest 的属性, 有点类似于字符串 Trie 中用来标识是不是一个单词结尾的属性, 这里表示的是从根节点到当前节点所组成的 path 是不是在 folder 中出现过, 在添加 path 的过程中, 如果遇到 is_shortest=true 的节点, 那就不必再添加下去, 因为下面的所有 path 都是这个节点的 sub folder, 不会出现在答案中。另一方面, 我们在添加过程中, 当我们走到 path 的末尾, 那我们要把当前节点的 is_shortest 设为 true
use std::collections::HashMap;
struct Node {
is_shortest: bool,
children: Tree,
}
struct Tree(HashMap<String, Node>);
impl Tree {
fn new() -> Self {
Self(HashMap::new())
}
fn add(&mut self, mut path: Vec<String>) {
if path.is_empty() {
return;
}
let section = path.remove(0);
if let Some(next) = self.0.get_mut(§ion) {
if next.is_shortest {
return;
}
if path.is_empty() {
next.is_shortest = true;
return;
}
next.children.add(path);
return;
}
let mut node = Node {
is_shortest: path.is_empty(),
children: Tree::new(),
};
node.children.add(path);
self.0.insert(section, node);
}
fn short_pathes(&self, curr: String, ans: &mut Vec<String>) {
for (k, v) in &self.0 {
let mut path = curr.clone();
path.push('/');
path.push_str(k);
if v.is_shortest {
ans.push(path);
continue;
}
v.children.short_pathes(path, ans);
}
}
}
impl Solution {
pub fn remove_subfolders(folder: Vec<String>) -> Vec<String> {
let mut tree = Tree::new();
for path in folder {
let sections: Vec<String> = path
.split("/")
.map(|s| s.to_owned())
.filter(|v| v != "")
.collect();
tree.add(sections);
}
let mut ans = Vec::new();
tree.short_pathes("".into(), &mut ans);
ans
}
}