返回

71. 简化路径 : 简单字符串模拟题

后端

引言

在计算机科学中,路径名是一种标识文件或目录在文件系统中位置的方法。在 Unix 风格的操作系统中,路径名通常由一个或多个目录名组成,这些目录名由斜杠 (/) 分隔。例如,/home/user/Documents 是一个指向用户“user”的“Documents”文件夹的路径名。

题目

本期要向你介绍的是一道经典的字符串模拟题,题目编号为 71,题名为“Simplify Path”。这是一道中等难度的题目,在 LeetCode 上的通过率为 50.8%。该题的标签为“模拟”和“栈”。

给你一个字符串 path,表示指向某一文件或目录的 Unix 风格绝对路径(以 / 开头)。请你将该路径简化。结果路径需要满足以下规则:

  • 所有路径组件都用 / 分隔,即不能出现连续的 //
  • 删除路径中所有值为 . 的组件,即表示当前目录。
  • 删除路径中所有值为 .. 的组件,即表示上一级目录。
  • 返回结果路径的绝对路径。

示例

输入:path = "/home/"
输出:"/home"
解释:注意,最后一个目录分隔符不需要移除。

输入:path = "/../"
输出:"/"
解释:从根目录向上一级目录是不可行的,因此返回根目录。

输入:path = "/home//foo/"
输出:"/home/foo"
解释:在第二个示例中,第二个目录分隔符是不必要的,因此需要将其删除。

输入:path = "/a/./b/../../c/"
输出:"/c"

输入:path = "/a/../../b/../c//.//"
输出:"/c"

算法

为了解决这个问题,我们可以使用一个栈来模拟文件系统的目录结构。栈是一个数据结构,它遵循后进先出的原则,即最后添加的元素将首先被移除。

首先,我们将路径字符串 path 分割成一个由目录名组成的列表。然后,我们将列表中的每个目录名依次压入栈中。当我们遇到一个 . 时,我们将其从栈中弹出,因为. 表示当前目录,而当前目录并不需要出现在最终的路径中。当我们遇到一个 .. 时,我们也将其从栈中弹出,同时将栈顶元素也弹出,因为 .. 表示上一级目录,而我们不需要返回到上一级目录。

最后,我们将栈中的所有目录名按照它们被压入栈的顺序依次连接起来,并返回结果路径。

时间复杂度

该算法的时间复杂度为 O(n),其中 n 为路径字符串 path 的长度。

空间复杂度

该算法的空间复杂度为 O(n),其中 n 为路径字符串 path 的长度。

代码

def simplify_path(path):
    """
    简化路径。

    Args:
        path: 指向某一文件或目录的 Unix 风格绝对路径(以 '/' 开头)。

    Returns:
        结果路径的绝对路径。
    """

    # 将路径字符串分割成一个由目录名组成的列表。
    components = path.split('/')

    # 使用栈来模拟文件系统的目录结构。
    stack = []

    # 将列表中的每个目录名依次压入栈中。
    for component in components:
        if component == '.':
            continue
        elif component == '..':
            if stack:
                stack.pop()
                if stack:
                    stack.pop()
        else:
            stack.append(component)

    # 将栈中的所有目录名按照它们被压入栈的顺序依次连接起来。
    result_path = '/' + '/'.join(stack)

    # 返回结果路径。
    return result_path

总结

本期向你介绍的这道题目是一道经典的字符串模拟题,难度为中等。该题的解法相对简单,我们可以使用栈来模拟文件系统的目录结构,并按照一定的规则来简化路径。希望这道题能够帮助你加深对栈数据结构的理解,也希望你能在 LeetCode 上取得好成绩!