Simplify Path
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"
.
但是对于我来说就是,需要搞清楚他到底有多少特殊规定。
比如题目不明显的规矩:
1 如何处理/./--直接忽略
2 如何处理/../--回退一个单词(目录)
3 第一个字符必须是'/'
还有明显的规矩:
4 双//处理
5 结尾单词后面不能接'/'
搞清楚之后就好写程序了,就是把一个一个规矩实现,写入新的字符串中。
这些问题都很细,需要耐心处理,而且每个人的处理方法好像都可以有点不一样,不过最主要的就是思路要清晰,不能乱。
下面是注释详细的程序,不带注释就是一团麻了,注释好,思路还算清晰的。
class Solution {
public:
string simplifyPath(string path)
{
string res;
//规矩1: 第一个必定是'/'
res.push_back('/');
for (int i = 1; i < path.length(); i++)
{
string ts = "";
//查找/ /之间的单词,保存在ts中
while (i<path.length() && path[i] != '/')
{
ts += path[i];
i++;
}
//规矩2:遇到..的时候要回退出上一个单词(目录)
if (ts == "..")
{
if (!res.empty() && res.back() == '/')
res.pop_back();
while (!res.empty() && res.back() != '/')
{
res.pop_back();
}
//注意:规矩1,第一个字符必须是'/'
if (res.empty()) res.push_back('/');
}
else if (ts == "")
{
//双个//的时候,只有在空的时候才加入'/';其他时候不用处理,默认i++就掠过了原字符串中的'/'了
if (res.empty())
res.push_back('/');
}
//规矩3:当遇到.的时候自动跃过,既不入栈,也i++,掠过'/'
else if (ts != ".")
{
res.append(ts);
res.push_back('/');
}
}
//规矩4:有单词的时候结尾不能为'/'
if (!res.empty() && res.back() == '/') res.pop_back();
//空的时候,当做第一个字符,遵循第一个规矩:第一个字符必须是'/'
if (res.empty()) return "/";
return res;
}
};
//2014-2-10 update
string simplifyPath(string path)
{
string rs("/");
for (int i = 1; i < path.length(); i++)
{
string tmp;
for ( ; i < path.length() && path[i] != '/'; i++)
tmp.push_back(path[i]);
if (tmp == "..")
{
if (rs.length() > 1) rs.pop_back();
while (rs.length()>1 && rs.back()!='/') rs.pop_back();
}
else if (!tmp.empty() && tmp != ".") rs.append(tmp+"/");
}
if (rs.length() > 1) rs.pop_back();
return rs;
}