LeetCode 388 文件的最长绝对路径
文章目录摘要描述题解答案题解代码分析1. 字符串分割2. 使用栈维护路径3. 计算层级4. 处理路径栈5. 计算当前路径长度6. 判断文件和目录7. 完整执行流程示例示例测试及结果示例 1input dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext示例 2input dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext示例 3input a示例 4input file1.txt\nfile2.txt\nlongfile.txt时间复杂度空间复杂度实际应用场景场景一文件系统操作场景二日志解析场景三配置文件解析场景四树形结构解析总结摘要这道题其实挺有意思的它要求我们解析一个用字符串表示的文件系统然后找到指向文件的最长绝对路径。听起来像是文件系统操作但实际上是一个字符串解析和路径计算的问题。关键点在于如何正确解析制表符\t来表示目录层级以及如何计算每个文件的绝对路径长度。这道题的核心在于如何理解制表符的层级关系以及如何维护当前路径的栈结构。今天我们就用 Swift 来搞定这道题顺便聊聊这种路径解析的方法在实际开发中的应用场景比如文件系统操作、日志解析、配置文件解析等等。描述题目要求是这样的给定一个用字符串表示的文件系统其中\n表示换行符\t表示制表符用来表示目录层级返回文件系统中指向文件的最长绝对路径的长度。如果系统中没有文件返回0。示例 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^4input可能包含小写或大写的英文字母一个换行符\n一个制表符\t一个点.一个空格 和数字。这道题的核心思路是什么呢我们需要按行分割字符串然后解析每行的制表符数量来确定层级使用栈来维护当前路径最后计算每个文件的绝对路径长度找到最长的。题解答案下面是完整的 Swift 解决方案classSolution{funclengthLongestPath(_input:String)-Int{// 按换行符分割字符串letlinesinput.components(separatedBy:\n)// 用栈来维护当前路径存储每层的路径长度varstack:[Int][]varmaxLength0forlineinlines{// 计算当前行的层级制表符的数量letlevelgetLevel(line)// 移除制表符获取实际内容letcontentline.replacingOccurrences(of:\t,with:)letcontentLengthcontent.count// 如果当前层级小于等于栈的深度需要弹出栈顶元素直到层级匹配whilestack.countlevel{stack.removeLast()}// 计算当前路径的长度// 如果栈为空说明是根目录路径长度就是内容长度// 如果栈不为空需要加上父路径长度和分隔符 /letcurrentLength:Intifstack.isEmpty{currentLengthcontentLength}else{currentLengthstack.last!1contentLength// 1 是分隔符 /}// 如果是文件包含 .更新最大长度ifcontent.contains(.){maxLengthmax(maxLength,currentLength)}else{// 如果是目录将当前路径长度压入栈stack.append(currentLength)}}returnmaxLength}// 计算行的层级制表符的数量privatefuncgetLevel(_line:String)-Int{varlevel0forcharinline{ifchar\t{level1}else{break}}returnlevel}}题解代码分析让我们一步步分析这个解决方案1. 字符串分割首先我们需要将输入字符串按换行符分割成多行letlinesinput.components(separatedBy:\n)components(separatedBy: \n)会将字符串按换行符分割成数组每一行代表文件系统中的一个条目文件或目录。2. 使用栈维护路径我们使用栈来维护当前路径的层级结构varstack:[Int][]栈中存储的是每一层的路径长度不包括当前层的名称。这样我们可以快速计算当前路径的总长度。为什么使用栈因为文件系统是树形结构当我们进入一个目录时需要记录当前路径当我们退出目录时需要回到上一级路径。栈的先进后出特性正好符合这种需求。3. 计算层级我们需要计算每行的层级也就是制表符的数量privatefuncgetLevel(_line:String)-Int{varlevel0forcharinline{ifchar\t{level1}else{break}}returnlevel}这个方法从字符串开头开始统计连续的制表符数量。制表符的数量就代表了目录的层级深度。示例dir→ level 0根目录\tsubdir1→ level 1一级子目录\t\tfile1.ext→ level 2二级子目录下的文件4. 处理路径栈当我们处理新的一行时需要根据层级调整栈// 如果当前层级小于等于栈的深度需要弹出栈顶元素直到层级匹配whilestack.countlevel{stack.removeLast()}这个逻辑很重要。如果当前行的层级小于栈的深度说明我们已经回到了上一级或更上级的目录需要弹出栈顶元素直到栈的深度等于当前层级。示例假设栈中存储的是[3, 11, 20]对应路径 “dir/subdir1/subsubdir1”当前行是\tsubdir2level 1。栈的深度是 3当前层级是 1需要弹出 2 个元素栈变成[3]这样栈就对应路径 “dir”符合当前层级5. 计算当前路径长度计算当前路径的总长度letcurrentLength:Intifstack.isEmpty{currentLengthcontentLength}else{currentLengthstack.last!1contentLength// 1 是分隔符 /}如果栈为空说明是根目录路径长度就是内容长度。如果栈不为空需要加上父路径长度和分隔符/。示例假设栈中存储的是[3]对应路径 “dir”当前内容是subdir1长度 7。当前路径长度 3“dir” 1‘/’ 7“subdir1” 11对应路径 “dir/subdir1”6. 判断文件和目录我们需要判断当前条目是文件还是目录ifcontent.contains(.){maxLengthmax(maxLength,currentLength)}else{stack.append(currentLength)}如果内容包含.说明是文件我们更新最大长度。如果是目录我们将当前路径长度压入栈供后续使用。为什么用.判断根据题目描述文件名遵循name.extension的格式所以包含.的就是文件。目录名不包含.。7. 完整执行流程示例让我们用一个例子来理解整个执行过程。假设输入是dir\n\tsubdir1\n\t\tfile1.ext\n\tsubdir2\n\t\tfile2.ext处理 “dir”level 0content “dir”contentLength 3栈为空currentLength 3是目录压入栈stack [3]处理 “\tsubdir1”level 1content “subdir1”contentLength 7栈深度 1等于 level不需要弹出currentLength 3 1 7 11是目录压入栈stack [3, 11]处理 “\t\tfile1.ext”level 2content “file1.ext”contentLength 9栈深度 2等于 level不需要弹出currentLength 11 1 9 21是文件更新 maxLength 21处理 “\tsubdir2”level 1content “subdir2”contentLength 7栈深度 2大于 level弹出栈顶stack [3]currentLength 3 1 7 11是目录压入栈stack [3, 11]处理 “\t\tfile2.ext”level 2content “file2.ext”contentLength 9栈深度 2等于 level不需要弹出currentLength 11 1 9 21是文件更新 maxLength max(21, 21) 21最终返回 21。示例测试及结果让我们用几个例子来测试一下这个解决方案示例 1input “dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext”执行过程处理 “dir”栈 [3]maxLength 0处理 “\tsubdir1”栈 [3, 11]maxLength 0处理 “\tsubdir2”栈 [3, 11]弹出后栈 [3]然后栈 [3, 11]maxLength 0处理 “\t\tfile.ext”currentLength 11 1 9 21maxLength 21**结果**返回20注意实际路径是 “dir/subdir2/file.ext”长度是 20不是 21让我重新计算dir/subdir2/file.ext 3 1 7 1 9 20示例 2input “dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext”执行过程处理 “dir”栈 [3]处理 “\tsubdir1”栈 [3, 11]处理 “\t\tfile1.ext”currentLength 11 1 9 21maxLength 21处理 “\t\tsubsubdir1”栈 [3, 11, 21]处理 “\tsubdir2”栈 [3, 11]弹出后栈 [3]然后栈 [3, 11]处理 “\t\tsubsubdir2”栈 [3, 11, 21]处理 “\t\t\tfile2.ext”currentLength 21 1 9 31maxLength 31**结果**返回32路径 “dir/subdir2/subsubdir2/file2.ext” 的长度让我重新计算dir/subdir2/subsubdir2/file2.ext 3 1 7 1 10 1 9 32示例 3input “a”执行过程处理 “a”level 0content “a”不包含 ‘.’是目录栈 [1]maxLength 0**结果**返回0没有文件示例 4input “file1.txt\nfile2.txt\nlongfile.txt”执行过程处理 “file1.txt”currentLength 9maxLength 9处理 “file2.txt”currentLength 9maxLength 9处理 “longfile.txt”currentLength 12maxLength 12**结果**返回12时间复杂度让我们分析一下这个算法的时间复杂度时间复杂度O(n)其中n是输入字符串的长度。分析字符串分割components(separatedBy: \n)需要遍历整个字符串一次时间复杂度 O(n)遍历所有行需要遍历所有行总字符数不超过 n时间复杂度 O(n)计算层级每行最多有 O(n) 个字符但所有行的总字符数是 n所以总时间复杂度 O(n)栈操作每个元素最多入栈和出栈一次总操作次数不超过行数时间复杂度 O(n)所以总时间复杂度是 O(n)这是最优的因为我们至少需要遍历一次字符串来解析它。对于题目约束input.length 10^4这个时间复杂度是完全可接受的。空间复杂度让我们分析一下这个算法的空间复杂度空间复杂度O(n)其中n是输入字符串的长度。分析字符串分割lines数组最多存储 O(n) 个字符空间复杂度 O(n)栈栈的深度最多等于目录的最大层级深度。在最坏情况下比如所有目录都是单层嵌套栈的深度是 O(n)临时变量其他临时变量占用 O(1) 空间所以总空间复杂度是 O(n)这是必要的因为我们需要存储解析后的数据。实际应用场景这种路径解析的方法在实际开发中应用非常广泛场景一文件系统操作在文件系统操作中我们经常需要解析文件路径计算路径长度等funcgetLongestFilePath(_fileSystem:String)-String?{// 解析文件系统字符串找到最长路径letsolutionSolution()letmaxLengthsolution.lengthLongestPath(fileSystem)// 返回最长路径returnfindPathWithLength(fileSystem,length:maxLength)}这种场景在文件管理器、备份工具等应用中经常用到。场景二日志解析在日志解析中我们可能需要解析带有层级结构的日志funcparseHierarchicalLog(_log:String)-[LogEntry]{letlineslog.components(separatedBy:\n)varstack:[LogEntry][]varentries:[LogEntry][]forlineinlines{letlevelgetLevel(line)letcontentline.replacingOccurrences(of:\t,with:)whilestack.countlevel{stack.removeLast()}letentryLogEntry(content:content,level:level,parent:stack.last)entries.append(entry)ifentry.isContainer{stack.append(entry)}}returnentries}这种场景在日志分析工具、调试工具等应用中经常用到。场景三配置文件解析在配置文件解析中我们可能需要解析带有缩进的配置文件funcparseIndentedConfig(_config:String)-ConfigNode{letlinesconfig.components(separatedBy:\n)varstack:[ConfigNode][]letrootConfigNode(name:root,children:[])stack.append(root)forlineinlines{letlevelgetIndentLevel(line)letcontentline.trimmingCharacters(in:.whitespaces)whilestack.countlevel1{stack.removeLast()}letnodeConfigNode(name:content,children:[])stack.last?.children.append(node)ifnode.isSection{stack.append(node)}}returnroot}这种场景在配置管理、数据解析等应用中经常用到。场景四树形结构解析在树形结构解析中我们经常需要处理带有缩进的数据funcparseTreeStructure(_data:String)-TreeNode{letlinesdata.components(separatedBy:\n)varstack:[TreeNode][]letrootTreeNode(value:root)stack.append(root)forlineinlines{letlevelgetLevel(line)letvalueline.replacingOccurrences(of:\t,with:)whilestack.countlevel1{stack.removeLast()}letnodeTreeNode(value:value)stack.last?.children.append(node)stack.append(node)}returnroot}这种场景在数据可视化、树形结构展示等应用中经常用到。总结这道题虽然看起来复杂但实际上是一个经典的栈应用问题。通过使用栈来维护路径层级我们可以清晰地处理各种情况。关键点总结栈的应用使用栈来维护当前路径的层级结构层级计算通过制表符数量来确定目录层级路径长度计算通过栈中存储的路径长度来快速计算当前路径长度文件判断通过是否包含.来判断是文件还是目录算法优势时间复杂度低只需要遍历字符串一次O(n)实现简单逻辑清晰容易理解和维护扩展性好可以很容易地扩展到处理更复杂的文件系统结构实际应用路径解析的方法在很多场景中都有应用比如文件系统操作、日志解析、配置文件解析、树形结构解析等。理解这种解析技术不仅能帮助我们解决类似的算法题还能让我们更好地处理各种层级结构的数据。

相关新闻

大数据领域数据交易的发展瓶颈与突破路径

大数据领域数据交易的发展瓶颈与突破路径

大数据领域数据交易的发展瓶颈与突破路径 关键词:数据交易、数据要素、隐私计算、数据确权、数据合规 摘要:数据作为“数字时代的石油”,正在成为驱动经济发展的核心生产要素。但当前数据交易市场仍面临“有数据不敢卖、有需求买不到、交易后…

2026/7/3 15:04:22 阅读更多 →
Vue + TS 报错「Argument not assignable」?3 步教你把类型对齐,函数立刻可调用!

Vue + TS 报错「Argument not assignable」?3 步教你把类型对齐,函数立刻可调用!

Vue TS 报错「Argument not assignable」?3 步教你把类型对齐,函数立刻可调用! 正文目录 报错含义:TypeScript 在挑剔什么参数?5 大高频翻车场景 & 修复代码万能兜底:类型断言与重载预防 checklist&…

2026/7/3 15:04:23 阅读更多 →
第21届全国大学生智能汽车竞赛讯飞组赛项:智慧工程

第21届全国大学生智能汽车竞赛讯飞组赛项:智慧工程

【编辑状态】

2026/7/3 15:04:26 阅读更多 →

最新新闻

UI自动化测试实战指南:从原理到工具选型与Selenium项目搭建

UI自动化测试实战指南:从原理到工具选型与Selenium项目搭建

1. 从“点点点”到“自动跑”:UI自动化测试到底是什么? 如果你是一名软件测试工程师,或者正在学习软件测试,那么“UI自动化测试”这个词你一定不陌生。它听起来很高大上,似乎充满了技术感,但它的本质其实很…

2026/7/6 9:55:12 阅读更多 →
SpringBoot+Vue2办公系统源码包:含审批流、日志填报、会议室预约与RBAC权限控制

SpringBoot+Vue2办公系统源码包:含审批流、日志填报、会议室预约与RBAC权限控制

本文还有配套的精品资源,点击获取 简介:开箱即用的轻量级OA系统,后端用SpringBoot 2.x MyBatis MySQL,前端基于Vue 2.6 Element UI构建,适配毕业设计和中小团队内部管理场景。功能覆盖公告管理、文件收发与档案归…

2026/7/6 9:55:12 阅读更多 →
JMeter录制脚本全攻略:从零搭建性能测试自动化流水线

JMeter录制脚本全攻略:从零搭建性能测试自动化流水线

1. 项目概述:为什么录制脚本是性能测试的“临门一脚” 刚接触性能测试的新手,常常会卡在第一步:脚本怎么写?手动在JMeter里一个个添加HTTP请求,配置参数、头信息,不仅效率低下,还容易出错&#…

2026/7/6 9:53:09 阅读更多 →
从零搭建可私有化部署的AI Agent:Hermes三层记忆架构与实战指南

从零搭建可私有化部署的AI Agent:Hermes三层记忆架构与实战指南

🚀 30款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度 最近在尝试将 AI Agent 从“玩具”升级为“生产力工具”时,发现了一个普遍痛点:很多教程要么停留在概念和 API…

2026/7/6 9:53:09 阅读更多 →
Python+Selenium UI自动化测试框架搭建:从PO模式到Pytest实战

Python+Selenium UI自动化测试框架搭建:从PO模式到Pytest实战

1. 项目概述与核心价值 最近在团队里做技术复盘,发现很多测试同学在尝试UI自动化时,总是一上来就埋头写脚本,结果代码越写越乱,维护成本高到离谱,最后项目不了了之。这让我想起几年前自己踩过的那些坑,所以…

2026/7/6 9:49:00 阅读更多 →
Kimi    LeetCode 3495. 使数组元素都变为零的最少操作次数 Rust实现

Kimi LeetCode 3495. 使数组元素都变为零的最少操作次数 Rust实现

这是 LeetCode 3495 的 Rust 实现。题目理解- 每个查询 [l, r] 定义数组 nums [l, l1, ..., r] - 每次操作选两个数 a, b,替换为 ⌊a/4⌋ 和 ⌊b/4⌋ - 求将所有元素变为 0 的最少操作次数核心思路一个数 x 变为 0 需要的操作次数是满足 4^p > x 的最小 p&#…

2026/7/6 9:49:00 阅读更多 →

日新闻

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2与MySQL单元测试兼容性:5个关键SQL语句差异与规避方案1. 单元测试中的数据库兼容性挑战在Java开发领域,单元测试是保证代码质量的重要环节。当应用涉及数据库操作时,测试环境的搭建往往成为开发者的痛点。H2数据库因其轻量级、内存模式和快…

2026/7/6 0:01:17 阅读更多 →
Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘 【免费下载链接】rbtray A fork of RBTray from http://sourceforge.net/p/rbtray/code/. 项目地址: https://gitcode.com/gh_mirrors/rb/rbtray 你是否厌倦了Windows任务栏上密密麻麻的图标&…

2026/7/6 0:01:17 阅读更多 →
Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C 运行时库一键安装终极指南:告别DLL缺失烦恼 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾经遇到过这样的情况:下载了…

2026/7/6 0:05:19 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/6 8:11:50 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/6 8:11:52 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/6 6:52:56 阅读更多 →

月新闻