avatar

目录
71简化路径

题目链接

题目描述:

以 Unix 风格给出一个文件的绝对路径,你需要简化它。或者换句话说,将其转换为规范路径。

在 Unix 风格的文件系统中,一个点(.)表示当前目录本身;此外,两个点 (..) 表示将目录切换到上一级(指向父目录);两者都可以是复杂相对路径的组成部分。更多信息请参阅:Linux / Unix中的绝对路径 vs 相对路径

请注意,返回的规范路径必须始终以斜杠 / 开头,并且两个目录名之间必须只有一个斜杠 /。最后一个目录名(如果存在)不能以 / 结尾。此外,规范路径必须是表示绝对路径的最短字符串。

示例 1:

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

示例 2:

输入:”/../“
输出:”/“
解释:从根目录向上一级是不可行的,因为根是你可以到达的最高级。

示例 3:

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

示例 4:

输入:”/a/./b/../../c/“
输出:”/c”

示例 5:

输入:”/a/../../b/../c//.//“
输出:”/c”

示例 6:

输入:”/a//b////c/d//././/..”
输出:”/a/b/c”


解题思路

  本题的难点在于耐心读题并且总结情况(if-else)。一开始我们要对输入路径进行预处理,在JS Array对象中有split方法,主要用于分割字符串返回为字符串数组,这里我们根据/分成输入路径的字符串数组。针对输入路径的不同情形,我总结出五种情况:

  1. 遇到 ..需要返回上一级,即弹出最近输入的文件名;
  2. 遇到.不作任何变化;
  3. 别忘了""实例3已经告诉了我们,当分割//时,split会形成""字符串加入数组。而遇到它,也不作任何变化;
  4. 剩下的就是需要输入的文件名
  5. 此外,根据实例2,如果最终栈为空,则需要返回/

  在JS中,Array对象提供了poppush方法可以模拟栈。不过,对于本题,我认为实际上是用不到栈的先进后出的特点~
  对于不太理解分割完成的字符串样式(尤其是"")的同学,可以自行在Chrome浏览器进行调试(右键->检查->Sources->打断点调试)~


JS版本

javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
var simplifyPath = function (path) {
let stack = [];
const str = path.split("/");

for (let i = 0; i < str.length; i++) {
if (str[i] === ".."){
if(stack.length != 0 ){
stack.pop();
}
}
else if (str[i] === "" || str[i] === "."){
continue;
}
else{
stack.push(str[i]);
}

}

if (stack.length == 0) {
return "/";
}

let result = "";
for (let i = 0; i < stack.length; i++) {
result += "/" + stack[i];
}

return result;
};

关于C++

  在c++中没有类似于split的现成函数,那怎么办呢?这时候可以考虑getline()函数,关于它的操作自行百度,这里只谈它在本题的作用。getline相当于splitfor循环的结合体,对于getline(ss, record, '/'),可解释为输入字符串流ss,遇到'/'就截断,而后record存储输入流信息,直到输入流无效(也就是完成整个字符串的分割)。此外,对于输入流ss的类型必须是stringsream,才能进行流的输入输出操作。注意,存储结果的数据结构并不需要stack,使用vector<string>也可实现结果且执行用时为4ms,因为通篇下来,并未使用过先进后出这一特性。


CPP

cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Solution {
public:
string simplifyPath(string path) {
stringstream ss(path);
vector<string> records;
string record = "";

while(getline(ss, record, '/')){
if(record == ".."){
if(records.size() != 0){
records.pop_back();
}
}
else if(record == "." || record == ""){
continue;
}
else{
records.push_back(record);
}
}

if(records.size() == 0)
return "/";

string result;
for(auto rec : records)
result += "/" + rec;

return result;

}
};

如果有错误或者不严谨的地方,请务必给予指正,十分感谢。

文章作者: breadhunter
文章链接: http://yoursite.com/2020/03/14/71%E7%AE%80%E5%8C%96%E8%B7%AF%E5%BE%84/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 breadhunter
打赏
  • 微信
    微信
  • 支付寶
    支付寶