每日一题:简化路径(栈

96 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

一、题目概述:

leetcode第71题:简化路径

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

在 Unix 风格的文件系统中,一个点(.)表示当前目录本身;此外,两个点 (..) 表示将目录切换到上一级(指向父目录);两者都可以是复杂相对路径的组成部分。任意多个连续的斜杠(即,'//')都被视为单个斜杠 '/' 。 对于此问题,任何其他格式的点(例如,'...')均被视为文件/目录名称。

请注意,返回的 规范路径 必须遵循下述格式:

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

这道题的题目比较长,简单来说就是把传入路径中的./../按其规则得到正确的path。类似于node中的path.resolve,主要解决绝对路径和相对路径混用的情况,但是我们这个题目没有path.resolve复杂。

示例 1:

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

示例 2:

输入:path = "/home/"
输出:"/home"
解释:注意,最后一个目录名后面没有斜杠。

示例 3:

输入:path = "/home//foo/"
输出:"/home/foo"
解释:在规范路径中,多个连续斜杠需要用一个斜杠替换。

二、思路分析:

栈结构的特点:先入后出,后入先出。(可以视为一个有底的桶)

  1. 这道题也是利用栈的特点
  2. 对应path我们可以用/分割,每一部分的情况可能是空字符串、.一个点、..两个点、xxx正常的路径字符。其中遇到正常的路径字符xxx时,我们需要入栈,记录下当前的目录。遇到的空、一个点,我们可以直接忽略。..两个点的情况我们需要返回上级目录,即出栈操作。

三、AC 代码:

/**
 * @param {string} path
 * @return {string}
 */
var simplifyPath = function(path) {
    const stack = []
    const pathArr = path.split('/')
    for(let i=0; i<pathArr.length;i++){
        const p = pathArr[i]
        // p为 ''和'.'直接忽略;'..'返回上一级(出栈一个);正常的字符串入栈
        if (p==='..') {
            stack.pop()
        } else if (p&&p!=='.') {
            stack.push(p)
        }
    }
    return '/'+stack.join('/')
};

四、总结:

延申:大家可能觉得上面的代码还行,但是当识别判断规则较多时就会产生一大堆的if...else的判断比较丑,且可读性较差。这种情况下那我们可以做一些设计模式:

// 可以将定义和使用分离开
// 定义规则
const obj = {
    '': stack=>stack,
    '.': stack=>stack,
    '..': stack=>{
        stack.pop();
        return stack;
    }
}
var simplifyPath = function(path) {
    const stack = []
    const pathArr = path.split('/')
    for(let i=0; i<pathArr.length;i++){
        const p = pathArr[i]
        if (p in obj) {
            obj[p](stack)
        } else {
            stack.push(p)
        }
    }
    return '/'+stack.join('/')
};