【字符串】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 ( n l o g n ) O(nlogn)
  • 空间复杂度: O ( n ) O(n)

方法二:前缀树


复杂度分析

  • 时间复杂度: O ( ) O()
  • 空间复杂度: O ( ) O()

猜你喜欢

转载自blog.csdn.net/qq_43539599/article/details/106845361