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"
.
class Solution { public: string simplifyPath(string path) { int len = path.length(); if (len < 2) return "/"; vector<string> spath; int p = -1, q = 0; // seperate the path into parts & simplify it with a stack while (q < len) { while (q < len && path[q] != '/') q++; if (p + 1 < q) { add_part_to_spath(path.substr(p + 1, q - p - 1), spath); } p = q; q++; } // build the final simplified path string res; for (int i=0; i<spath.size(); i++) { res.push_back('/'); res.append(spath[i]); } if (res.length() == 0) res = "/"; return res; } void add_part_to_spath(string part, vector<string>& spath) { if (part == ".") { // do nothing; } else if (part == "..") { // goto the parent path part if (!spath.empty()) spath.pop_back(); } else { // enter a new part spath.push_back(part); } } };
也可以直接在原有字符串上操作,但还是这样简单明了一些
再写一次:
class Solution { public: string simplifyPath(string path) { vector<string> tokens; int len = path.size(); int last = 0; for (int i=0; i<len; i++) { char ch = path[i]; if (ch == '/') { if (i - last > 0) { push_token(path.substr(last, i - last), tokens); } last = i + 1; } } if (len - last > 0) { push_token(path.substr(last, len - last), tokens); } return token_path(tokens); } string token_path(vector<string>& tokens) { string path; for (string& token : tokens) { path = path + "/" + token; } if (tokens.empty()) { path = "/"; } return path; } void push_token(string token, vector<string>& tokens) { if (token == ".") { // nothing } else if (token == "..") { if (!tokens.empty()) { tokens.pop_back(); } } else { tokens.push_back(token); } } };