Given a list of folders, remove all sub-folders in those folders and return in any order the folders after removing.
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.
输入一个字符串数组floder,需要输出去掉所有子目录的一个List<String>
,输入的字符串都是目录的路径,且以"/"
开头
若folder = ["/a","/a/b","/c/d","/c/d/e","/c/f"]
/a/b
是/a
的子目录,/c/d/e
是/c/d
的子目录,删去这两个,输出为["/a","/c/d","/c/f"]
最容易想到的是直接使用List
放置结果,然后遍历folder
,伪代码如下:
for (String s1: folder)
for (String s2: ret) { // ret是List<String>类型
if (s1是s2子目录)
break;
if (s2是s1子目录) {
ret中的s2替换为s1
break;
}
ret中添加s1
}
判断子目录可以是拿出两个子目录对照,也可以把当前目录的父目录拿出来一个一个查,然后再查当前目录是不是其他的父目录
举例:当前目录为/a/b/c
,先去找ret
(List<String>
类型)中是否有/a
,再看是否有/a/b
,最后去掉ret
中没有以/a/b/c/
开头的,然后添加/a/b/c/
前两步是看有没有父目录,后一步是看有没有当前目录的子目录,前两步在ret
中挨个查找,效率很低,如果使用Set,那么就很好解决了,每次只要看父目录在Set中是否存在,后一步有两种办法
- 遍历Set然后判断是不是以
/a/b/c开头的
- 按照顺序遍历,
"/a/b", "/a"
这个顺序,只进行前半部分的判断,是没有办法将它们筛选掉的,但是如果它们顺序为"/a", "/a/b"
,就可以筛选掉/a/b
,所以如果正序倒序都建立一个Set,就可以分别去除掉在后面和前面子目录,然后取出两个Set中的公共部分,就是结果,最终代码如下:
class Solution {
public List<String> removeSubfolders(String[] folder) {
List<String> ret = new ArrayList<String>();
Set<String> set1 = new HashSet<String>();
Set<String> set2 = new HashSet<String>();
// 正序和反序分别生成的set
for (int i=0; i<folder.length; i++)
addEle(set1, folder[i]);
for (int i=folder.length-1; i>=0; i--)
addEle(set2, folder[i]);
// 提取出共同的部分,添加到ret中
for (String s: set1)
if (set2.contains(s))
ret.add(s);
return ret;
}
private void addEle(Set<String> set, String s) {
int index = 1, nextIndex = 0;
// 如果set中有s的父目录,那么当前目录就不需要添加到set中了
while ((nextIndex = s.indexOf('/', index)) != -1) {
if (set.contains(s.substring(0, nextIndex)))
return;
index = nextIndex + 1;
}
// set中不存在s的父目录,所以添加s
set.add(s);
}
}
网友评论