【字符串】B050_LC_刪除子文件夾(排序 + 記錄根文件夾 / trie 樹優化)

一、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 數組排序(字典序),那麼子父文件夾就越有可能被放到相鄰位置。
  • 如果當前文件夾 f[i]f[i] 是上一個父文件夾的子文件夾,那麼將 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;
    }
}

複雜度分析

  • 時間複雜度:O(nlogn)O(nlogn)
  • 空間複雜度:O(n)O(n)

方法二:前綴樹


複雜度分析

  • 時間複雜度:O()O()
  • 空間複雜度:O()O()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章