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源码拿出来考了。
我不知道Linux源码是如何实现的,我的想法是用一个栈来存储每一层的文件夹名称。如果遇到”.”的话,就忽略。如果遇到”..”的话,就pop栈顶,代表返回上一层。
需要注意,它在corner case中提到,如果返回上一层超过了root的话,比如”/../”,则记为”/”。如果多个”//”重复出现的话,则只取一个”/”进行判断。
代码写的有点乱,这里我用了一个vector<string>来存储每一层的文件夹名称,不用stack的原因是vector可以在最后输出结果时提供从底到顶的遍历。
我用了isNewLayer来区分当前读取到的’/’是新文件夹名的结束还是旧文件夹名的开始。
C++代码如下
class Solution {
public:
string simplifyPath(string path) {
vector<string> s;
string re;
size_t len = path.size();
if(len == 1) return path;
int start = 1; // start point to the first char of a new directory
size_t i = 1;// warning: program may skip to line 73 directly
bool isNewLayer = false;
string layer;
while(i < len){
if(path[i] == '/'){
//a new layer found
if(isNewLayer == true){
isNewLayer = false;
layer = path.substr(start, i - start);
start = i + 1; //warning: start may exceed the range
//current layer, ignore it
if (layer == "."){
;
}
//upper layer, pop one layer
else if(layer == ".."){
//no upper layer
if(s.empty()){
;
}
else{
s.pop_back();
}
}
//a new layer name
else{
s.push_back(layer);
}
}
//not a new layer
else{
start = i + 1; //warning: start may exceed the range
}
}
//current char is not a '/'
else{
isNewLayer = true;
}
i++;
}
if(start < i){
layer = path.substr(start, i - start);
//current layer
if(layer == "."){
;
}
//upper layer
else if(layer == ".."){
//root layer
if(s.empty()){
;
}
else{
s.pop_back();
}
}
else{
s.push_back(layer);
}
}
for(size_t i = 0; i < s.size(); i++){
re.push_back('/');
re.append(s[i]);
}
if(s.size() == 0){
re.push_back('/');
}
return re;
}
};
有空看下Linux源码。