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.mzph.cn/web/67015.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何在gitee/github上面搭建obsidian的图床

在搭建图床之前我们需要知道图床是一个什么东西,图床顾名思义就是存放图片的地方&#xff0c;那么我们为什么要搭建图床呢&#xff1f;因为我们在写博客的时候&#xff0c;很多同学都是在本地使用typora或者是obsidian进行markdown语法的文章的书写&#xff0c;文件格式通常都是…

JVM堆空间

JVM&#xff08;Java虚拟机&#xff09;堆空间是Java内存管理的核心区域之一&#xff0c;用于存储Java对象实例。以下是关于JVM堆空间的详细介绍&#xff1a; 1. 堆空间的作用 • 存储对象实例&#xff1a;几乎所有的Java对象实例&#xff08;通过new关键字创建的对象&#xf…

Redis 的热 Key(Hot Key)问题及解决方法

Redis 的热 Key&#xff08;Hot Key&#xff09;问题及解决方法 1. 什么是 Redis 热 Key&#xff1f; Redis 热 Key&#xff08;Hot Key&#xff09;指的是访问频率极高的 Key&#xff0c;通常会造成以下问题&#xff1a; 单 Key 访问量过大&#xff1a;热点 Key 可能被高并…

SSM东理咨询交流论坛

&#x1f345;点赞收藏关注 → 添加文档最下方联系方式咨询本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345; 项目视频 js…

http的请求体各项解析

一、前言 做Java开发的人员都知道&#xff0c;其实我们很多时候不单单在写Java程序。做的各种各样的系统&#xff0c;不管是PC的 还是移动端的&#xff0c;还是为别的系统提供接口。其实都离不开http协议或者https 这些东西。Java作为编程语言&#xff0c;再做业务开发时&#…

gradle生命周期钩子函数

文章目录 0. 总结表格1. 构建初始阶段gradle.settingsEvaluated()gradle.projectsLoaded() 2. 配置阶段gradle.beforeProject()gradle.afterProject()gradle.projectEvaluated()gradle.afterEvaluate()gradle.taskGraph.whenReady 3. 执行阶段gradle.taskGraph.beforeTaskgradl…

Qt Enter和HoverEnter事件

介绍 做PC开发的过程中或多或少都会接触到鼠标的悬停事件&#xff0c;Qt中处理鼠标悬停有Enter和HoverEnter两种事件 相同点 QEvent::Enter对应QEnterEvent&#xff0c;描述的是鼠标进入控件坐标范围之内的行为&#xff0c;QEnterEvent可以抓取鼠标的位置&#xff1b;QEvent…

【云安全】云原生-Docker(五)容器逃逸之漏洞利用

漏洞利用逃逸 通过漏洞利用实现逃逸&#xff0c;主要分为以下两种方式&#xff1a; 1、操作系统层面的内核漏洞 这是利用宿主机操作系统内核中的安全漏洞&#xff0c;直接突破容器的隔离机制&#xff0c;获得宿主机的权限。 攻击原理&#xff1a;容器本质上是通过 Linux 的…

如何优化深度学习模型来提高错别字检测准确率?

为了优化深度学习模型以提高错别字检测的准确率,可以从以下几个方面入手: 1. 数据增强 数据增强是提高模型泛化能力的有效方法。通过在训练数据中引入噪声,模型可以学习到更多变的模式,从而提高对未见数据的识别能力。 删除字符:以一定概率删除文本中的一个字符。增加字…

二叉搜索树中的搜索(力扣700)

首先介绍一下什么是二叉搜索树。 二叉搜索树是一个有序树&#xff1a; 若它的左子树不空&#xff0c;则左子树上所有结点的值均小于它的根结点的值&#xff1b;若它的右子树不空&#xff0c;则右子树上所有结点的值均大于它的根结点的值&#xff1b;它的左、右子树也分别为二叉…

pytest自动化测试 - 构造“预置条件”的几种方式

<< 返回目录 1 pytest自动化测试 - 构造“预置条件”的几种方式 1.1 使用夹具构造预置条件 在夹具章节中&#xff0c;我们介绍了夹具的作用&#xff0c;其中一项就是构造预置条件。pytest.fixture装饰器中如果测试数据使用yield返回&#xff0c;则yield前的语句为预置条…

微信小程序date picker的一些说明

微信小程序的picker是一个功能强大的组件&#xff0c;它可以是一个普通选择器&#xff0c;也可以是多项选择器&#xff0c;也可以是时间、日期、省市区选择器。 官方文档在这里 这里讲一下date picker的用法。 <view class"section"><view class"se…

[java] 面向对象进阶篇1--黑马程序员

目录 static 静态变量及其访问 实例变量及其访问 静态方法及其访问 实例方法及其访问 总结 继承 作用 定义格式 示例 总结 子类不能继承的内容 继承后的特点 成员变量 成员变量不重名 成员变量重名 super访问父类成员变量 成员方法 成员方法不重名 成员方法…

python3+TensorFlow 2.x 基础学习(一)

目录 TensorFlow 2.x基础 1、安装 TensorFlow 2.x 2、TensorFlow 2.x 基础概念 2、1 Eager Execution 2、2 TensorFlow 张量&#xff08;Tensor&#xff09; 3、使用Keras构建神经网络模型 3、1 构建 Sequential 模型 3、2 编译模型 1、Optimizer&#xff08;优化器&a…

AI News(1/21/2025):OpenAI 安全疏忽:ChatGPT漏洞引发DDoS风险/OpenAI 代理工具即将发布

1、OpenAI 的安全疏忽&#xff1a;ChatGPT API 漏洞引发DDoS风险 德国安全研究员 Benjamin Flesch 发现了一个严重的安全漏洞&#xff1a;攻击者可以通过向 ChatGPT API 发送一个 HTTP 请求&#xff0c;利用 ChatGPT 的爬虫对目标网站发起 DDoS 攻击。该漏洞源于 OpenAI 在处理…

openlava/LSF 用户组管理脚本

背景 在openlava运维中经常需要自动化一些常规操作&#xff0c;比如增加用户组以及组成员、删除用户组成员、删除用户组等。而openlava的配置文件需要手动修改&#xff0c;然后再通过badmin reconfig激活配置。因此开发脚本将手工操作自动化就很有必要。 通过将脚本中的User…

LLMs的星辰大海:大语言模型的前世今生

文章目录 一. LLM 的演进&#xff1a;从规则到智能的跃迁 &#x1f4ab;1.1 语言模型的蹒跚起步 &#x1f476;1.2 RNN 与 LSTM&#xff1a;序列建模的尝试 &#x1f9d0;1.3 Transformer 的横空出世&#xff1a;自注意力机制的革命 &#x1f4a5;1.4 LLM &#xff1a;从预测到…

7-Zip高危漏洞CVE-2025-0411:解析与修复

7-Zip高危漏洞CVE-2025-0411&#xff1a;解析与修复 免责声明 本系列工具仅供安全专业人员进行已授权环境使用&#xff0c;此工具所提供的功能只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利…

数据结构(精讲)----树(应用篇)

特性&#xff1a; 什么是树&#xff1a; 树(Tree)是(n>0)个节点的有限集合T&#xff0c;它满足两个条件&#xff1a; (1) 有且仅有一个特定的称为根&#xff08;Root&#xff09;的节点。 (2) 其余的节点可以分为m&#xff08;m≥0&#xff09;个互不相交的有限集合T1、…

【动态规划】--- 斐波那契数模型

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏&#xff1a; 算法Journey &#x1f3e0; 第N个泰波那契数模型 &#x1f4cc; 题目解析 第N个泰波那契数 题目要求的是泰波那契数&#xff0c;并非斐波那契数。 &…