[演算法分析與設計] leetcode 每週一題: 071. Simplify Path
阿新 • • 發佈:2019-02-11
題目連結:
題目大意:
給定一個 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