1. 程式人生 > >[演算法分析與設計] leetcode 每週一題: 071. Simplify Path

[演算法分析與設計] leetcode 每週一題: 071. Simplify Path



題目連結: 

題目大意:

給定一個 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