今天刷了一道中档题,感觉中档题还是有一点难度的,下面就和大家分享一下经验吧!
题目如下:
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//bc/d//././/.."
Output: "/a/b/c"
题意分析:
给定文件的Unix型绝对路径,请简化它。 或者说,将其转换为规范路径。在UNIX型的文件系统中,一个点(.)指的是当前目录,两个点(..)指返回上级目录。
注:返回的规范路径必须始终以斜杠(/)开头,并且两个目录名之间必须只有一个斜杠(/),最后一个目录名称(如果存在)不得后接斜杠(/)来结尾。另外,规范路径必须是表示绝对路径的最短字符串。
解答如下:
方法一(堆栈法)
由题目中的6个例子可以总结到:目录如果后接"."则直接去掉".",如果后接".."则删掉它的上级目录。如果被给绝对路径为空则返回"/",如果被给绝对路径中有多个连续"/"只保留一个。正因为如此,可以把被给绝对路径看做是由一个或多个"/"分割开的多个子字符串,利用两个while循环可以把这些子字符串分别提取出来并一一处理,而这些被提取出来的子字符串只有三种情况:①路径名称;②两个点"..";③一个点".",所以用if条件语句进行判断很容易求解。
class Solution{
public:
string simplifyPath(string path){
vector<string> tmp;
int i = 0;
while( i < path.size() ){
while( path[i] == '/' && i < path.size() ) i++;
if(i == path.size()) break; //用于避免被给绝对路径为空的情况,同时避免给规范路径的末尾增加斜杠‘/’
int start = i;
while( path[i] != '/' && i < path.size() ) i++;
int end = i - 1;
string s = path.substr( start, end - start +1); //将子字符串分别提取出来并一一处理
if( s == ".." )
{if( !tmp.empty() ) tmp.pop_back();} //返回上一级目录
else if( s != "." )
tmp.push_back(s); //tmp用于存放规范路径每一级的目录名称
}
if (tmp.empty()) return "/";
string res;
for (int i = 0; i < tmp.size(); ++i) {
res += '/' + tmp[i];
}
return res;
}
};
提交后的结果如下:
方法二(使用函数分隔字符串):
用stringstream函数替代两个while循环来分隔字符串,然后对每一个子字符串进行处理,大体的思路与方法一是一致的。
class Solution {
public:
string simplifyPath(string path) {
string res, t;
stringstream subs (path);
vector<string> tmp;
while (getline(subs, t, '/')) { //按斜杠'/'来分隔字符串,其中连续多个斜杠也会被分隔
if( t == ".." )
{if( !tmp.empty() ) tmp.pop_back();} //返回上一级目录
else if( t != "." && t != "" ) //这里多了一种为空的情况
tmp.push_back(t);
}
for (string s : tmp) res += "/" + s;
return res.empty() ? "/" : res;
}
};
提交后的结果如下:
日积月累,与君共进,增增小结,未完待续。