题目:
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. String compare函数
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数据结构的强大和使用方便。以后要好好利用。