題目:
Given an absolute path for a file (Unix-style), simplify it. Or in other words, convert it to the canonical path.
In a UNIX-style file system, a period . refers to the current directory. Furthermore, a double period … moves the directory up a level. For more information, see: Absolute path vs relative path in Linux/Unix
Note that the returned canonical path must always begin with a slash /, and there must be only a single slash / between two directory names. The last directory name (if it exists) must not end with a trailing /. Also, the canonical path must be the shortest string representing the absolute path.
Example 1:
Input: “/home/”
Output: “/home”
Explanation: Note that there is no trailing slash after the last directory name.
Example 2:
Input: “/…/”
Output: “/”
Explanation: Going one level up from the root directory is a no-op, as the root level is the highest level you can go.
Example 3:
Input: “/home//foo/”
Output: “/home/foo”
Explanation: In the canonical path, multiple consecutive slashes are replaced by a single one.
Example 4:
Input: “/a/./b/…/…/c/”
Output: “/c”
Example 5:
Input: “/a/…/…/b/…/c//.//”
Output: “/c”
Example 6:
Input: “/a//b////c/d//././/…”
Output: “/a/b/c”
絕對路徑和相對路徑的區別
見ABSOLUTE PATH VS RELATIVE PATH IN LINUX/UNIX
Example 4: My present location is /etc/lvm and I want to change my location to /opt/oradba
Using relative path:
cd …/…/opt/oradba
解法:
首先我們將目標字符串按照"/“來分割
由於字符串第一個字符爲”/",所以會切割出來一個空字符串""
然後依次進行處理,如果是空字符串或者是".",代表當前目錄,我們直接可以忽略不管
如果是"…",代表是父親目錄,我們直接去除我們上一個加入的目錄,此時我們要注意如果此時沒有目錄添加進來,我們是不能去除上一層目錄,我們可以使用出棧操作,
在c++中可以使用vector中的pop_back()操作,在java中可以使用LinkedList的removeLast來去除最後一個元素
剩下的情況,我們直接添加目錄即可,但是我們要判斷此時的字符串不是"…",如果字符串爲"…“而目錄不爲空,直接我們在之前的if條件中已經判斷過了,但是目錄爲空的條件下,如果我們不加判斷字符串不是”…“會將”…"錯誤的加入到目錄中去。
如:"/a/./b/…/…/c/"
分割的第一個爲空字符串忽略
分割的第二個爲a,加入列表a
分割的第三個爲. 忽略
分割的第四個爲b,加入列表a,b
分割的第四個爲…, 這代表父親目錄,即當前目錄爲b,b的父親目錄爲a,所以我們要去除b目錄,列表a
分割的第五個爲…, 這代表父親目錄,即當前目錄爲a,b的父親目錄爲根目錄,所以我們要去除a目錄,列表爲空、
分割的第六個爲c,加入列表爲c
然後我們將列表中的元素用"/“連接起來,注意我們要在最前面加上”/"
c++:
c++中沒有連接函數,我們只有遍歷列表,然後在每個元素前加上"/",最後如果列表爲空,我們直接輸出"/"就可以了
c++中用stringstream類來實現分割功能,getline(ss,t,’/’)函數最後一個參數是字符
class Solution {
public:
string simplifyPath(string path) {
string res,t;
stringstream ss(path);
vector<string> v;
while(getline(ss,t,'/')){
cout << t + "hahaha" << endl;
if(t == "" || t == ".") continue;
if(t == ".." && !v.empty()) v.pop_back();
else if(t != "..") v.push_back(t);
}
for(string s : v){
res += "/" + s;
}
return v.empty() ? "/" : res;
}
};
java:
split函數是分割,String.join函數是連接,有兩個參數,第一個是連接符,第二個是連接的列表
class Solution {
public String simplifyPath(String path) {
LinkedList<String> v = new LinkedList<>();
String[] paths = path.split("/");
for(String t : paths){
//System.out.println(t + "hahaha");
if(t.equals("") || t .equals(".") ) continue;
if(t.equals("..") && !v.isEmpty()) v.removeLast();
else if(!t.equals("..")) v.add(t);
}
String res = String.join("/",v);
//System.out.println(v);
return "/" + res;
}
}
python:
如果不用continue,可以對條件取非,再加上if條件
如在本例中, if(t == “” || t == “.”) continue; 可以改爲if t != “” and t != “.”
python中的連接函數爲 連接符.join() 參數爲列表
class Solution(object):
def simplifyPath(self, path):
"""
:type path: str
:rtype: str
"""
paths = [p for p in path.split("/") if p != "" and p!= "."]
res = []
for p in paths:
if p == ".." and res:
res.pop()
elif p != "..":
res.append(p)
return "/" + "/".join(res)