题目:
Given an absolute path for a file (Unix-style), simplify it.
For example,
path = "/home/"
, => "/home"
path = "/a/./b/../../c/"
, => "/c"
Corner Cases:
- Did you consider the case where path =
"/../"
?In this case, you should return
"/"
. - Another corner case is the path might contain multiple slashes
‘/‘
together,
such as"/home//foo/"
.In this case, you should ignore redundant slashes and return
"/home/foo"
.
思路:这是Linux内核中较常见的一个操作,就是对一个输入的文件路径进行简化。我们先来了解一下这些符号在Unix路径中代表的意义:
- “/.” 表示本级目录,可以忽略
- “/..” 表示返回上一级目录,即若上一级目录存在,连同“/..”一并删除,否则只删除“/..”
- 若去除冗余后路径为空,返回“/”
- 若包含多个连续“/”, 删除多余的“/”
在了解了我们要做的操作后,我们想到要维护一个栈,对于每一个块(用“/”作为分隔符)进行分析,如果遇到“../”表示要回到上一层,那么就进行出栈操作(如果栈不为空),如果遇到“./”表示在当前层,则直接跳过,不作操作,其他文件的路径则直接进栈,放在栈尾部。最后根据栈中的内容转换成路径即可,注意我们这里使用list双向链表的特性,和java LinkedList类似,list也包含了栈和队列的实现。这样在还原路径时,我们就不需要再维护一个栈来解决路径的顺序问题了,直接从栈头出栈就可以了。
Attention:
1. C++ list双向链表。
获得元素函数:front(); back();
进出栈/队列函数:push_back(); pop_back(); push_front(); pop_front();
我们可以根据自己的需求,来选择合适的函数进行操作。
2. Stringcompare函数
int compare (const string& str) const;
如果相等,返回0;
if(tmp.compare(".") == 0)
3. 如果去除冗余后路径为空,返回“/”
if(ret.size() == 0) return "/";
4. 注意如何获取分隔符“/”之间的元素,并进行操作,我们遍历一遍path.
while(i < path.size()) { int index = i; //截取‘/’之间的字符串 string tmp; while(i < path.size() && path[i] != '/') { tmp += path[i]; i++; }
5. 先获取队列头的元素,再pop_front(), 转换成正常路径。
while(!stk.empty()) { ret += "/" + stk.front(); stk.pop_front(); }
复杂度:O(N) 空间也是O(N),栈的大小
AC Code:
class Solution { public: string simplifyPath(string path) { if(path.size() == 0) return ""; list<string> stk; string ret; int i = 0; while(i < path.size()) { int index = i; //截取‘/’之间的字符串 string tmp; while(i < path.size() && path[i] != '/') { tmp += path[i]; i++; } if(index != i) { if(tmp.compare(".") == 0) { continue; } else if(tmp.compare("..") == 0) { if(!stk.empty()) { stk.pop_back(); } } else { stk.push_back(tmp); } } i++; } while(!stk.empty()) { ret += "/" + stk.front(); stk.pop_front(); } if(ret.size() == 0) return "/"; return ret; } };
这道题,我们也可以用数组来存储分隔符之间的元素,这样就可以直接通过下标来操作元素。数组也有push_back和pop_back函数。可以看下这篇博文:Simplify Path
不过通过这道题,了解到C++ list数据结构的强大和使用方便。以后要好好利用。