一、Problem
你是一位系統管理員,手裏有一份文件夾列表 folder,你的任務是要刪除該列表中的所有 子文件夾,並以 任意順序 返回剩下的文件夾。
我們這樣定義「子文件夾」:
如果文件夾 folder[i] 位於另一個文件夾 folder[j] 下,那麼 folder[i] 就是 folder[j] 的子文件夾。
文件夾的「路徑」是由一個或多個按以下格式串聯形成的字符串:
/ 後跟一個或者多個小寫英文字母。
例如,/leetcode 和 /leetcode/problems 都是有效的路徑,而空字符串和 / 不是。
輸入:folder = ["/a","/a/b","/c/d","/c/d/e","/c/f"]
輸出:["/a","/c/d","/c/f"]
解釋:"/a/b/" 是 "/a" 的子文件夾,而 "/c/d/e" 是 "/c/d" 的子文件夾。
輸入:folder = ["/a/b/c","/a/b/d","/a/b/ca"]
輸出:["/a/b/c","/a/b/ca","/a/b/d"]
提示:
1 <= folder.length <= 4 * 10^4
2 <= folder[i].length <= 100
folder[i] 只包含小寫字母和 /
folder[i] 總是以字符 / 起始
每個文件夾名都是唯一的
方法一:記錄根目錄
雙重循環檢查很簡單,但會超時。
- 可以先對 folders 數組排序(字典序),那麼子父文件夾就越有可能被放到相鄰位置。
- 如果當前文件夾 是上一個父文件夾的子文件夾,那麼將 root 設置爲當前文件夾,並跳過當前文件夾。
- 然後繼續枚舉下去,重複第 2 點。
細節:這裏的判斷子父文件夾的時候不能直接比較兩個字符串,因爲給出的某些文件夾是沒有 / 結尾的,我們要先將 / 添加到根目錄字符串的後面,否則會 WA,比如
folder = ["/a/b/c","/a/b/d","/a/b/ca"]
這就只會輸出 ["/a/b/c","/a/b/d"]
因爲這裏誤認爲 "/a/b/ca" 是 "/a/b/c" 的子文件夾了
class Solution {
boolean startsWith(String cur, String root) {
int i;
for (i = 0; i < root.length(); i++) if (root.charAt(i) != cur.charAt(i)) {
return false;
}
return cur.charAt(--i) == '/';
}
public List<String> removeSubfolders(String[] fs) {
Arrays.sort(fs);
List<String> ans = new LinkedList<>();
ans.add(fs[0]);
String root = fs[0] + "/";
int n = fs.length;
for (int i = 1; i < n; i++) {
if (!startsWith(fs[i], root)) {
root = fs[i] + "/";
ans.add(fs[i]);
}
}
return ans;
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,
方法二:前綴樹
複雜度分析
- 時間複雜度:,
- 空間複雜度:,