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 原题链接和其他优选题解。

相关文章
|
存储 SQL Java
Springboot Mybatis 、JPA 调用存储过程,实战教程
Springboot Mybatis 、JPA 调用存储过程,实战教程
1964 0
Springboot Mybatis 、JPA 调用存储过程,实战教程
|
监控 数据可视化 安全
智慧工地源码:数字孪生智慧工地可视化解决方案
智慧工地源码:数字孪生智慧工地可视化解决方案
425 0
|
算法 测试技术 数据安全/隐私保护
【软件工程期末复习】知识点+大题详解(E-R图、数据流图、N-S盒图、状态图、活动图、用例图....)(下)
【软件工程期末复习】知识点+大题详解(E-R图、数据流图、N-S盒图、状态图、活动图、用例图....)
5344 0
|
新零售 Dubbo Java
Java编程详解-基于 dubbo 的分布式架构
前言 现在越来越多的互联网公司还是将自己公司的项目进行服务化,这确实是今后项目开发的一个趋势,就这个点再凭借之前的 SSM 项目来让第一次接触的同学能快速上手。
1742 0
|
Web App开发 关系型数据库 测试技术
OJ搭建详细
学校ACM部需要一个比赛的平台~于是找到hustoj架设方法如下:资料来源于:https://code.google.com/p/hustoj/wiki/ HUST JOL安装说明 by zhblue(newsclan@gmail.
2795 0
|
6天前
|
缓存 人工智能 自然语言处理
我对比了8个Claude API中转站,踩了不少坑,总结给你
本文是个人开发者耗时1周实测的8大Claude中转平台横向评测,聚焦Claude Code真实体验:以加权均价(¥/M token)、内部汇率、缓存支持、模型真实性及稳定性为核心指标。
2480 17
|
18天前
|
人工智能 自然语言处理 安全
Claude Code 全攻略:命令大全 + 实战工作流(建议收藏)
本文介绍了Claude Code终端AI助手的使用指南,主要内容包括:1)常用命令如版本查看、项目启动和更新;2)三种工作模式切换及界面说明;3)核心功能指令速查表,包含初始化、压缩对话、清除历史等操作;4)详细解析了/init、/help、/clear、/compact、/memory等关键命令的使用场景和语法。文章通过丰富的界面截图和场景示例,帮助开发者快速掌握如何通过命令行和交互界面高效使用Claude Code进行项目开发,特别强调了CLAUDE.md文件作为项目知识库的核心作用。
15938 47
Claude Code 全攻略:命令大全 + 实战工作流(建议收藏)
|
24天前
|
人工智能 数据可视化 安全
王炸组合!阿里云 OpenClaw X 飞书 CLI,开启 Agent 基建狂潮!(附带免费使用6个月服务器)
本文详解如何用阿里云Lighthouse一键部署OpenClaw,结合飞书CLI等工具,让AI真正“动手”——自动群发、生成科研日报、整理知识库。核心理念:未来软件应为AI而生,CLI即AI的“手脚”,实现高效、安全、可控的智能自动化。
34944 57
王炸组合!阿里云 OpenClaw X 飞书 CLI,开启 Agent 基建狂潮!(附带免费使用6个月服务器)
|
13天前
|
人工智能 JavaScript Ubuntu
低成本搭建AIP自动化写作系统:Hermes保姆级使用教程,长文和逐步实操贴图
我带着怀疑的态度,深度使用了几天,聚焦微信公众号AIP自动化写作场景,写出来的几篇文章,几乎没有什么修改,至少合乎我本人的意愿,而且排版风格,也越来越完善,同样是起码过得了我自己这一关。 这个其实OpenClaw早可以实现了,但是目前我觉得最大的区别是,Hermes会自主总结提炼,并更新你的写作技能。 相信就冲这一点,就值得一试。 这篇帖子主要就Hermes部署使用,作一个非常详细的介绍,几乎一步一贴图。 关于Hermes,无论你赞成哪种声音,我希望都是你自己动手行动过,发自内心的选择!
3050 29