题目链接:
题目大意:
给定一个 Unix 风格的 path, 给出一个简化的版本 ;
题中还注明了 对顶层目录 的假设, 见下方 例3 ;
例如: 给定: "/home/", 则输出应为: "/home" ;
例如: 给定: "/a/./b/../../c/", 则输出应为: "/c" ;
例如: 给定: "/../", 则输出应为: "/" ;
解题过程:
(1) 题意很简单, 由于关键是对 corner case 的处理, 所以我大致上就直接按工程的做法做了 ;
(2) 就用最老实的做法, 逐项处理 ; 针对 "当前目录" 符号 "./", 直接忽略 ; 针对 "父目录" 符号 "../" 考虑利用栈来处理 (中间还要假设顶层目录是 "/") ;
代码如下:
class Solution {
public:
using Path = string;
Path withoutRedundantSlash( const Path & s ) {
Path ret;
ret.push_back( s.front() );
for ( size_t i = 1; i < s.size(); i++ ) {
if ( s[i] == '/' && s[i - 1] == '/' ) {
continue;
}
ret.push_back( s[i] );
}
return ret;
}
Path withoutTailSlash( const Path & s ) {
auto ret = s;
while ( ret.size() > 1 && ret.back() == '/' ) {
ret.pop_back();
}
return ret;
}
Path withoutRedundantDot( const Path & s ) {
vector< Path > segments;
size_t head = 0;
for ( size_t i = head; i < s.size(); i++ ) {
if ( s[i] == '/' ) {
segments.push_back( s.substr( head, i - head ) );
head = i + 1;
}
}
if ( head < s.size() ) {
segments.push_back( s.substr( head ) );
}
vector< Path > dirs;
for ( size_t i = 0; i < segments.size(); i++ ) {
auto d = segments[i];
if ( d == ".." ) {
if ( dirs.size() <= 1 ) {
// FIXME: ignore heading `./` case
continue;
}
dirs.pop_back();
} else if ( d == "." ) {
continue;
} else {
dirs.push_back( d + "/" );
}
}
Path ret;
for ( size_t i = 0; i < dirs.size(); i++ ) {
auto d = dirs[i];
ret += d;
}
return ret;
}
// FIXME: assume filepath
Path simplifyPath( Path path ) {
Path ret = path;
// cerr << ret << endl;
ret = withoutRedundantSlash( ret );
// cerr << ret << endl;
ret = withoutRedundantDot( ret );
// cerr << ret << endl;
ret = withoutTailSlash( ret );
return ret;
}
};
Runtime: 6 ms