当前位置: 首页 > article >正文

leetcode 面试经典 150 题:简化路径

链接简化路径
题序号71
题型字符串
解法
难度中等
熟练度✅✅✅

题目

  • 给你一个字符串 path ,表示指向某一文件或目录的 Unix 风格 绝对路径 (以 ‘/’ 开头),请你将其转化为 更加简洁的规范路径。

  • 在 Unix 风格的文件系统中规则如下:
    一个点 ‘.’ 表示当前目录本身。
    此外,两个点 ‘…’ 表示将目录切换到上一级(指向父目录)。
    任意多个连续的斜杠(即,‘//’ 或 ‘///’)都被视为单个斜杠 ‘/’。
    任何其他格式的点(例如,‘…’ 或 ‘…’)均被视为有效的文件/目录名称。

  • 返回的 简化路径 必须遵循下述格式:
    始终以斜杠 ‘/’ 开头。
    两个目录名之间必须只有一个斜杠 ‘/’ 。
    最后一个目录名(如果存在)不能 以 ‘/’ 结尾。
    此外,路径仅包含从根目录到目标文件或目录的路径上的目录(即,不含 ‘.’ 或 ‘…’)。
    返回简化后得到的 规范路径 。

  • 示例 1
    输入:path = “/home/”
    输出:“/home”
    解释:
    应删除尾随斜杠。

  • 示例 2
    输入:path = “/home//foo/”
    输出:“/home/foo”
    解释:
    多个连续的斜杠被单个斜杠替换。

  • 示例 3
    输入:path = “/home/user/Documents/…/Pictures”
    输出:“/home/user/Pictures”
    解释:
    两个点 “…” 表示上一级目录(父目录)。

  • 示例 4
    输入:path = “/…/”
    输出:“/”
    解释:
    不可能从根目录上升一级目录。

  • 示例 5
    输入:path = “/…/a/…/b/c/…/d/./”
    输出:“/…/b/d”
    解释:
    “…” 在这个问题中是一个合法的目录名。

  • 提示
    1 <= path.length <= 3000
    path 由英文字母,数字,‘.’,‘/’ 或 ‘_’ 组成。
    path 是一个有效的 Unix 风格绝对路径。

题型

  1. 核心思想:该题使用栈(Stack)这种数据结构来模拟路径的遍历和回退过程。
  2. 复杂度:时间复杂度是 O(n),其中 n 是路径字符串的长度,因为我们需要遍历整个字符串。空间复杂度也是 O(n),因为我们需要存储路径的有效部分。
  3. c++ 实现算法
class Solution {
public:
    std::string simplifyPath(std::string path) {

        std::vector<std::string> stack;//定义一个栈
        
        //创建了一个 std::stringstream 对象 ss,并将字符串 path 作为其初始内容。
        //这样做的目的是为了方便地对路径字符串进行分割和读取操作。
        std::stringstream ss(path);
        //dir 用于存储从 stringstream 中读取的每个目录
        std::string dir;
        
        //使用 getline 函数从 stringstream 中按 / 分割读取路径的每个部分,直到没有更多内容可读。
        while (getline(ss, dir, '/')) {
            //如果目录为空字符串或为 ".",表示当前目录,不做任何操作,继续下一次循环。
            if (dir.empty() || dir == ".") {
                continue;
            }
            //如果目录为 "..",表示返回上一级目录。如果栈不为空,则弹出栈顶元素(即移除上一级目录)。
            else if (dir == "..") {
                if (!stack.empty()) {
                    stack.pop_back();
                }
            }
            //否则,将该目录压入栈中。 
            else {
                stack.push_back(dir);
            }
        }
        //初始化一个空字符串 simplified,用于存储简化后的路径。然后遍历栈中的每个目录,
        //将其添加到 simplified 字符串中,并在每个目录前加上 /。
        std::string simplified;
        for (const std::string& d : stack) {
            simplified += "/" + d;
        }
        
        //simplified 为空字符串,说明路径简化后是一个根目录,返回 /。否则,返回 simplified。
        return simplified.empty() ? "/" : simplified;
    }
};
  1. 算法推演
  • 初始化
    stack:[]
    ss:/a/./b/…/…/c/

  • 遍历路径

    • 读取第一个部分:“”
      空字符串,忽略。
      stack:[]

    • 读取第二个部分:“a”
      将 “a” 压入栈。
      stack:[“a”]

    • 读取第三个部分:“.”
      当前目录,忽略。
      stack:[“a”]

    • 读取第四个部分:“b”
      将 “b” 压入栈。
      stack:[“a”, “b”]

    • 读取第五个部分:“…”
      返回上一级目录,弹出栈顶元素 “b”。
      stack:[“a”]

    • 读取第六个部分:“…”
      返回上一级目录,弹出栈顶元素 “a”。
      stack:[]

    • 读取第七个部分:“c”
      将 “c” 压入栈。
      stack:[“c”]

  • 构建简化后的路径
    初始化 simplified:“”
    遍历栈中的每个目录,将其添加到 simplified 字符串中,并在每个目录前加上 /。
    simplified:“/c”

  • 返回结果
    simplified 不为空,返回 “/c”

  • 最终结果
    简化后的路径为:“/c”

  1. c++ 完整demo
#include <iostream>
#include <vector>
#include <string>
#include <sstream>

class Solution {
public:
    std::string simplifyPath(std::string path) {

        std::vector<std::string> stack;//定义一个栈
        
        //创建了一个 std::stringstream 对象 ss,并将字符串 path 作为其初始内容。
        //这样做的目的是为了方便地对路径字符串进行分割和读取操作。
        std::stringstream ss(path);
        //dir 用于存储从 stringstream 中读取的每个目录
        std::string dir;
        
        //使用 getline 函数从 stringstream 中按 / 分割读取路径的每个部分,直到没有更多内容可读。
        while (getline(ss, dir, '/')) {
            //如果目录为空字符串或为 ".",表示当前目录,不做任何操作,继续下一次循环。
            if (dir.empty() || dir == ".") {
                continue;
            }
            //如果目录为 "..",表示返回上一级目录。如果栈不为空,则弹出栈顶元素(即移除上一级目录)。
            else if (dir == "..") {
                if (!stack.empty()) {
                    stack.pop_back();
                }
            }
            //否则,将该目录压入栈中。 
            else {
                stack.push_back(dir);
            }
        }
        //初始化一个空字符串 simplified,用于存储简化后的路径。然后遍历栈中的每个目录,
        //将其添加到 simplified 字符串中,并在每个目录前加上 /。
        std::string simplified;
        for (const std::string& d : stack) {
            simplified += "/" + d;
        }
        
        //simplified 为空字符串,说明路径简化后是一个根目录,返回 /。否则,返回 simplified。
        return simplified.empty() ? "/" : simplified;
    }
};

int main() {
    Solution solution;
    std::string path = "/home//foo/";
    std::string simplifiedPath = solution.simplifyPath(path);
    std::cout << "Simplified Path: " << simplifiedPath << std::endl;
    return 0;
}

http://www.kler.cn/a/521992.html

相关文章:

  • 【Rust自学】15.7. 循环引用导致内存泄漏
  • 浅析百度AOI数据与高德AOI数据的差异性
  • DPO、KTO、DiffusionDPO
  • 在Ubuntu上用Llama Factory命令行微调Qwen2.5的简单过程
  • 4.flask-SQLAlchemy,表Model定义、增删查改操作
  • Node.js基础
  • 鲁滨逊漂流记读后感
  • 【PySide6快速入门】QGridLayout 网格布局
  • 如何使用 DeepSeek API 结合 VSCode 提升开发效率
  • 深度学习笔记13-CIFAR彩色图片识别(Pytorch)
  • 供应链管理中的BOM 和 MRP 是什么,如何计算
  • 探索前端可观察性:如何使用Telemetry提高用户体验
  • 基于Java+Springboot+MySQL校园在线考试网站系统设计与实现
  • zyNo.19
  • 解析“in the wild”——编程和生活中的俚语妙用
  • 八股——Java基础(四)
  • 【PySide6拓展】QLCDNumber类lcd 显示数字
  • 多级缓存(亿级并发解决方案)
  • C#常用257单词
  • 基于RIP的MGRE实验
  • MySQL 主从同步报错:`Unknown or incorrect time zone` 问题全解析
  • 【GESP】2024 C++ 一级编程题解析及测试信息下载
  • UART ,IIC 和SPI三种总线协议
  • C# 中 [MethodImpl(MethodImplOptions.Synchronized)] 的使用详解
  • Tensor 基本操作5 device 管理,使用 GPU 设备 | PyTorch 深度学习实战
  • 低代码系统-产品架构案例介绍、明道云(十一)