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.
輸入一個字符串數(shù)組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);
}
}