LeetCode 刷題記錄 71. Simplify Path

題目:
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)
                
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章