Topic link
Title description:
Given the absolute path of a file in Unix style, you need to simplify it. Or in other words, convert it to a canonical path.
In a Unix-style file system, a dot (.) indicates the current directory itself; in addition, two dots (...) indicate that the directory is switched to the upper level (pointing to the parent directory); both can be composed of complex relative paths section. For more information, please refer to: Absolute Path vs Relative Path in Linux/Unix
Please note that the returned canonical path must always start with a slash /, and there must be only one slash / between the two directory names. The last directory name (if it exists) cannot end with /. In addition, the canonical path must be the shortest string representing an absolute path.
Example 1:
Input: "/home/"
Output: "/home"
Explanation: Note that there is no slash after the last directory name.
Example 2:
Input: "/.../"
Output: "/"
Explanation: It is not feasible to go one level up from the root directory, because the root is the highest level you can reach.
Example 3:
Input: "/home//foo/"
Output: "/home/foo"
Explanation: In the canonical path, multiple consecutive slashes need to be replaced with one slash.
Example 4:
Input: "/a/./b/…/…/c/"
Output: "/c"
Example 5:
Input: "/a/…/…/b/…/c//.//"
Output: "/c"
Example 6:
Input: "/a//bc/d//././/..."
Output: "/a/b/c"
Problem-solving ideas
The difficulty of this question is to read the question patiently and summarize the situation ( if-else
). At the beginning, we need to preprocess the input path. There are split
methods in the JS Array object, which are mainly used to split the string and return it to a string array. Here we /
divide the string array into the input path. For different situations of the input path, I summarized five situations:
- Encountered
..
need to return to the previous level, the file name pops up recently entered; .
Do not make any changes when encountered ;- Don't forget
""
, we实例3
have already told us that when splitting//
, itsplit
will form a""
string and join the array. And when you encounter it, do not make any changes; - The rest is the file name that needs to be entered
- In addition, according to
实例2
, if the final stack is empty, it needs to return/
.
In JS, the Array object provides pop
and push
methods to simulate the stack. However, for this question, I think that the first-in-last-out feature of the stack is actually not used.
For ""
students who do not understand the split string style (especially ), you can debug it in the Chrome browser by yourself (right click -> 检查
-> Sources
->Breakpoint debugging)~
JS version
var simplifyPath = function (path) {
let stack = [];
const str = path.split("/");
for (let i = 0; i < str.length; i++) {
if (str[i] === ".."){
if(stack.length != 0 ){
stack.pop();
}
}
else if (str[i] === "" || str[i] === "."){
continue;
}
else{
stack.push(str[i]);
}
}
if (stack.length == 0) {
return "/";
}
let result = "";
for (let i = 0; i < stack.length; i++) {
result += "/" + stack[i];
}
return result;
};
About C++
There is no similar split
ready-made function in C++ , so what should I do? At this time, you can consider the getline()
function. Regarding its operation, Baidu will only talk about its role in this question. getline
Equivalent split
and for
loop combination, for getline(ss, record, '/')
, interpretable input string stream is ss
encountered '/'
on the cut, and then record
storing the input information stream, until the input stream is not valid (i.e. the entire string divided completed). In addition, ss
the type of input stream must be stringsream
in order to perform stream input and output operations. Note that the data structure for storing the result is not required stack
, vector<string>
and the result can be realized by using it and the execution time is 4ms, because throughout the article, the first-in-last-out feature has not been used.
CPP
class Solution {
public:
string simplifyPath(string path) {
stringstream ss(path);
vector<string> records;
string record = "";
while(getline(ss, record, '/')){
if(record == ".."){
if(records.size() != 0){
records.pop_back();
}
}
else if(record == "." || record == ""){
continue;
}
else{
records.push_back(record);
}
}
if(records.size() == 0)
return "/";
string result;
for(auto rec : records)
result += "/" + rec;
return result;
}
};
If there are mistakes or not rigorous, please correct me, thank you very much.
My blog: http://breadhunter.gitee.io