388. 文件的最长绝对路径 : 哈希表模拟题

简介: 388. 文件的最长绝对路径 : 哈希表模拟题

网络异常,图片无法展示
|


题目描述



这是 LeetCode 上的 388. 文件的最长绝对路径 ,难度为 中等


Tag : 「模拟」、「哈希表」


假设有一个同时存储文件和目录的文件系统。下图展示了文件系统的一个示例:


网络异常,图片无法展示
|


这里将 dir 作为根目录中的唯一目录。dir 包含两个子目录 subdir1subdir2


subdir1 包含文件 file1.ext 和子目录 subsubdir1subdir2 包含子目录 subsubdir2,该子目录下包含文件 file2.ext


在文本格式中,如下所示(⟶表示制表符):


dir
⟶ subdir1
⟶ ⟶ file1.ext
⟶ ⟶ subsubdir1
⟶ subdir2
⟶ ⟶ subsubdir2
⟶ ⟶ ⟶ file2.ext
复制代码


如果是代码表示,上面的文件系统可以写为

"dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext"'\n''\t' 分别是换行符和制表符。


文件系统中的每个文件和文件夹都有一个唯一的 绝对路径 ,即必须打开才能到达文件/目录所在位置的目录顺序,所有路径用 '/' 连接。上面例子中,指向 file2.ext 的 绝对路径 是 "dir/subdir2/subsubdir2/file2.ext" 。每个目录名由字母、数字和/或空格组成,每个文件名遵循 name.extension 的格式,其中 nameextension 由字母、数字和/或空格组成。


给定一个以上述格式表示文件系统的字符串 input ,返回文件系统中 指向 文件 的 最长绝对路径 的长度 。 如果系统中没有文件,返回 00


示例 1:


网络异常,图片无法展示
|


输入:input = "dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext"
输出:20
解释:只有一个文件,绝对路径为 "dir/subdir2/file.ext" ,路径长度 20
复制代码


示例 2:


网络异常,图片无法展示
|


输入:input = "dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext"
输出:32
解释:存在两个文件:
"dir/subdir1/file1.ext" ,路径长度 21
"dir/subdir2/subsubdir2/file2.ext" ,路径长度 32
返回 32 ,因为这是最长的路径
复制代码


示例 3:


输入:input = "a"
输出:0
解释:不存在任何文件
复制代码


示例 4:


输入:input = "file1.txt\nfile2.txt\nlongfile.txt"
输出:12
解释:根目录下有 3 个文件。
因为根目录中任何东西的绝对路径只是名称本身,所以答案是 "longfile.txt" ,路径长度为 12
复制代码


提示:


  • 1 <= input.length <= 10^41<=input.length<=104
  • input 可能包含小写或大写的英文字母,一个换行符 '\n',一个制表符 '\t',一个点 '.',一个空格 ' ',和数字。


模拟 + 哈希表



为了方便,我们将 input 替换为 s


对于每一个文件或文件夹而言,我们可以通过访问到结尾(\n)的方式取得,记为 cur,然后根据 cur 前面有多少个 \t 得知其所在的层级,假设当前其所在层级为 level,那么它自然归属到最新一个层级为 level - 1 的文件夹中,因此我们可以使用哈希表记录每个层级最新的文件夹路径,通过字符串拼接的方式得到 cur 所在的完整路径 path,并在处理整个 s 过程中,统计长度最大的文件路径。


代码:


class Solution {
    public int lengthLongestPath(String s) {
        Map<Integer, String> map = new HashMap<>();
        int n = s.length();
        String ans = null;
        for (int i = 0; i < n; ) {
            int level = 0;
            while (i < n && s.charAt(i) == '\t' && ++level >= 0) i++;
            int j = i;
            boolean isDir = true;
            while (j < n && s.charAt(j) != '\n') {
                if (s.charAt(j++) == '.') isDir = false;
            }
            String cur = s.substring(i, j);
            String prev = map.getOrDefault(level - 1, null);
            String path = prev == null ? cur : prev + "/" + cur;
            if (isDir) map.put(level, path);
            else if (ans == null || path.length() > ans.length()) ans = path;
            i = j + 1;
        }
        return ans == null ? 0 : ans.length();
    }
}
复制代码


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


优化



上述做法只是为了方便我们输出具体方案。


实际上,我们只关心最终的路径长度,而不关心具体路径,因此容易将解法一修改为只记录长度,而不记录路径的做法,从而避免掉字符串拼接带来的消耗,同时利用 s 的长度数据范围,使用数组来替代常数较大的哈希表。


代码:


class Solution {
    static int[] hash = new int[10010];
    public int lengthLongestPath(String s) {
        Arrays.fill(hash, -1);
        int n = s.length(), ans = 0;
        for (int i = 0; i < n; ) {
            int level = 0;
            while (i < n && s.charAt(i) == '\t' && ++level >= 0) i++;
            int j = i;
            boolean isDir = true;
            while (j < n && s.charAt(j) != '\n') {
                if (s.charAt(j++) == '.') isDir = false;
            }
            Integer cur = j - i;
            Integer prev = level - 1 >= 0 ? hash[level - 1] : -1;
            Integer path = prev + 1 + cur;
            if (isDir) hash[level] = path;
            else if (path > ans) ans = path;
            i = j + 1;
        }
        return ans;
    }
}
复制代码


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


最后



这是我们「刷穿 LeetCode」系列文章的第 No.388 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。


在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。


为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:github.com/SharingSour…


在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。

相关文章
|
9月前
|
存储 算法
【每日挠头算法题(6)】二叉树的所有路径|神奇字符串
【每日挠头算法题(6)】二叉树的所有路径|神奇字符串
|
2月前
|
算法 测试技术 C#
【字典树】【字符串】【 前缀】100268. 最长公共后缀查询
【字典树】【字符串】【 前缀】100268. 最长公共后缀查询
|
2月前
|
算法 测试技术 C#
【字典树】【KMP】【C++算法】3045统计前后缀下标对 II
【字典树】【KMP】【C++算法】3045统计前后缀下标对 II
|
2月前
|
Python C++ 机器人
C/C++每日一练(20230419) 插入区间、单词拆分、不同路径
C/C++每日一练(20230419) 插入区间、单词拆分、不同路径
27 0
C/C++每日一练(20230419) 插入区间、单词拆分、不同路径
|
2月前
|
存储 算法 Java
给定一个二叉树,请你找出其中最长严格递增路径的长度。(提示:使用动态规划)
给定一个二叉树,请你找出其中最长严格递增路径的长度。(提示:使用动态规划)
22 0
|
2月前
【每日一题Day135】LC1487保证文件名唯一 | 哈希表
【每日一题Day135】LC1487保证文件名唯一 | 哈希表
17 0
|
7月前
|
C++
LeetCode | 双法妙解压缩字符串【遍历统计 + 双指针】
LeetCode | 双法妙解压缩字符串【遍历统计 + 双指针】
35 0
|
存储 算法 测试技术
LeetCode算法小抄--O(1)时间下删除-查找数组中任意元素
LeetCode算法小抄--O(1)时间下删除-查找数组中任意元素
|
算法
Leetcode-每日一题1234. 替换子串得到平衡字符串(滑动窗口 + 哈希表)
简介: 版权声明:本文为博主原创文章,未经博主允许不得转载。https://blog.csdn.net/weixin_46618592/article/details/129004869?spm=1001.2014.3001.5502
144 0
Leetcode-每日一题1234. 替换子串得到平衡字符串(滑动窗口 + 哈希表)
|
存储 Windows
每日一题——文件的最长绝对路径
每日一题——文件的最长绝对路径
98 0
每日一题——文件的最长绝对路径