题目:
Given an absolute path for a file (Unix-style), simplify it. Or in other words, convert it to the canonical path.
In a UNIX-style file system, a period .
refers to the current directory. Furthermore, a double period ..
moves the directory up a level. For more information, see: Absolute path vs relative path in Linux/Unix
Note that the returned canonical path must always begin with a slash /
, and there must be only a single slash /
between two directory names. The last directory name (if it exists) must not end with a trailing /
. Also, the canonical path must be the shortest string representing the absolute path.
Example 1:
Input: "/home/" Output: "/home" Explanation: Note that there is no trailing slash after the last directory name.
Example 2:
Input: "/../" Output: "/" Explanation: Going one level up from the root directory is a no-op, as the root level is the highest level you can go.
Example 3:
Input: "/home//foo/" Output: "/home/foo" Explanation: In the canonical path, multiple consecutive slashes are replaced by a single one.
Example 4:
Input: "/a/./b/../../c/" Output: "/c"
Example 5:
Input: "/a/../../b/../c//.//" Output: "/c"
Example 6:
Input: "/a//b////c/d//././/.." Output: "/a/b/c"
描述:
给出一个字符串表示unix系统下的路径,尝试输出该路径简化后的结果,要求,
路径必须以 / 开始,不能以 / 结尾,相邻两级目录之间只能有一个 / ,
. 表示当前目录,..表示上级目录,/ 为根目录,其上级目录是 /
分析:
用current标记已简化部分的末尾位置,随后遍历该路径,
分情况讨论,
1,遇到 / 时,若current处不为 / ,则放入 / ,否则不操作
2, 若遇到单个 "."(".." 或 ".a" 这种不算单个 "."),则跳过,不处理
3, 若遇到 ".." ( “..a” 或 "..." 不算),分情况讨论:
1), 若current所在不为根目录,则current回退到上一个 / 的位置处重新开始
2), 否则跳过这两个点
4, 对于其他情况,认为是路径名,添加到有效的path中
最后注意去掉可能存在的多余的 "/"
样例:
"/..."
"/.a"
"/home/"
"/../"
"/home//foo/"
"/a/./b/../../c/"
"/a/../../b/../c//.//"
"/a//b////c/d//././/.."
代码:(时间复杂度 O (n),空间复杂度O (1),因为只使用了path本身的空间)
class Solution {
public:
string simplifyPath(string path) {
int current = 0;
for (int i = 1; i < path.size(); ++ i) {
if (path[i] == '/') {
if (path[current] != '/') {
path[++ current] = '/';
}
} else if (onePoint(path, i)) {//只有一个点
++ i;
} else if (twoPoint(path, i)) {//有连续两个点
if (current) {//若非根目录
-- current;
while (path[current] != '/') {
-- current;
}
} else {
++ i;//跳过这两个点
}
} else {//对于其他情况,认为是路径名
while (i < path.size() && path[i] != '/') {
path[++ current] = path[i];
++ i;
}
-- i;
}
}
if (!current || path[current] != '/') {
++ current;
}
return path.substr(0, current);
}
bool onePoint(const string &s, int index) {
if (s[index] != '.') {//当前位置不为点
return false;
}
if (index + 1 >= s.size()) {//已到顶部
return true;
}
return s[index + 1] == '/';
}
bool twoPoint(const string &s, int index) {
if (s[index] != '.' || index + 1 >= s.size() || s[index + 1] != '.') {//当前位置不为点
return false;
}
++ index;
if (index + 1 >= s.size()) {//已到顶部
return true;
}
return s[index + 1] == '/';
}
};