【中等】力扣算法题解析LeetCode388:文件的最长绝对路径

关注文末推广名片,即可免费获得本题测试源码

题目来源:LeetCode 388. 文件的最长绝对路径

问题抽象: 给定一个表示文件目录结构的字符串 input(由换行符 '\n'、制表符 '\t' 和字母组成),要求计算所有 文件绝对路径 的最大长度(包括目录名和文件名之间的分隔符 '/'),满足以下核心需求:

  1. 结构解析规则

    • 每行表示一个文件或目录,由换行符分隔;
    • 行首制表符数量表示深度(根目录深度 0,无制表符);
    • 文件绝对路径为从根目录到文件的完整路径(如 "dir/subdir/file.ext")。
  2. 路径构建要求

    • 路径分隔符为 '/'(非系统相关);
    • 路径长度包括所有目录名、文件名和分隔符(不含制表符和换行符);
    • 仅对文件(名称含 . 和扩展名)计算路径长度。
  3. 计算约束

    • 时间复杂度 O(n)n 为字符串长度),空间复杂度 O(d)d 为最大深度);
    • 使用 维护当前路径:
      • 栈存储各层路径累计长度;
      • 每行解析:统计制表符数得深度,弹出栈顶直到栈深等于当前深度;
      • 当前项长度 = 栈顶值(若栈非空)+ 1(分隔符)+ 名称长度;
      • 若为文件,更新最大长度;若为目录,压栈当前长度。
  4. 边界处理

    • 空字符串 → 返回 0
    • 无文件 → 返回 0
    • 特殊输入:
      • "dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext" → 最长路径 "dir/subdir2/file.ext" 长度 20
      • "a.txt"(单文件)→ 路径 "a.txt" 长度 5
      • "a"(单目录)→ 无文件,返回 0
      • "dir\n\tfile1.txt\n\tsubdir\n\t\tfile2.txt" → 最长路径 "dir/subdir/file2.txt" 长度 18
    • 深度递增约束:连续制表符(如 "\t\t" 表示深度 2)。

输入:字符串 input(长度 ≥0)。
输出:整数值(最长文件绝对路径长度,无文件时返回 0)。


解题思路

题目要求计算文件系统中文件绝对路径的最大长度。输入字符串使用\n表示换行,\t表示层级关系,包含扩展名(如.txt)的项被视为文件。

核心思路是使用一个数组模拟栈,记录每一层目录的累计路径长度(包括目录名和分隔符),遍历每一行:

  1. 计算层级:统计行首的\t个数作为当前层级。
  2. 获取名称:移除行首的\t后得到当前文件或目录的名称。
  3. 计算路径长度
    • 根目录(层级0):路径长度 = 名称长度。
    • 非根目录:路径长度 = 上一层级累计长度 + 当前名称长度。
  4. 更新结果
    • 若是文件(名称含.),更新最大路径长度。
    • 若是目录,将当前路径长度 + 1(加1是为下一级添加分隔符/)存入栈中,供下一层级使用。

此方法时间复杂度为O(n),空间复杂度为O(n),n为输入行数。


代码实现(Java版)🔥点击下载源码

class Solution {
    public int lengthLongestPath(String input) {
        if (input == null || input.isEmpty()) {
            return 0;
        }
        // 按换行符分割输入字符串
        String[] lines = input.split("\n");
        int n = lines.length;
        // 栈数组:stack[i]存储第i层的最新路径长度(含结尾分隔符)
        int[] stack = new int[n];
        int maxLen = 0; // 记录最大文件路径长度
        
        for (String line : lines) {
            // 计算层级:统计行首的\t个数
            int level = 0;
            while (level < line.length() && line.charAt(level) == '\t') {
                level++;
            }
            // 获取当前名称(移除行首\t)
            String name = line.substring(level);
            int nameLen = name.length();
            
            // 计算当前完整路径长度
            int curLen;
            if (level == 0) {
                curLen = nameLen; // 根目录
            } else {
                // 非根目录:父层级路径长度 + 当前名称长度
                curLen = stack[level - 1] + nameLen;
            }
            
            // 判断是否为文件(名称包含.)
            if (name.contains(".")) {
                maxLen = Math.max(maxLen, curLen); // 更新最大长度
            } else {
                // 目录:存储当前路径长度+1(为下一级预留分隔符/)
                if (level < n) {
                    stack[level] = curLen + 1;
                }
            }
        }
        return maxLen;
    }
}

代码说明

  1. 输入处理:使用split("\n")将输入分割成行数组。
  2. 层级计算:遍历行首字符统计\t数量确定层级。
  3. 名称提取:通过substring(level)移除行首\t获取纯净名称。
  4. 路径长度计算
    • 根目录(level=0)路径长度等于名称长度。
    • 非根目录路径长度 = 父层级栈值(stack[level-1]) + 当前名称长度。
  5. 文件判断:名称包含.视为文件,更新maxLen
  6. 目录处理:目录路径长度需加1(末尾分隔符/)后存入栈,供子级使用。

提交详情(执行用时、内存消耗)

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

达文汐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值