1. 程式人生 > 其它 >LC 388 檔案的最長路徑

LC 388 檔案的最長路徑

LC 388 檔案的最長路徑

題目描述

假設有一個同時儲存檔案和目錄的檔案系統。下圖展示了檔案系統的一個示例:

這裡將 dir 作為根目錄中的唯一目錄。dir 包含兩個子目錄 subdir1 和 subdir2 。subdir1 包含檔案 file1.ext 和子目錄 subsubdir1;subdir2 包含子目錄 subsubdir2,該子目錄下包含檔案 file2.ext 。

在文字格式中,如下所示(⟶表示製表符):

dir
⟶ subdir1
⟶ ⟶ file1.ext
⟶ ⟶ subsubdir1
⟶ subdir2
⟶ ⟶ subsubdir2
⟶ ⟶ ⟶ file2.ext

如果是程式碼表示,上面的檔案系統可以寫為 "dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext" 。'\n' 和 '\t' 分別是換行符和製表符。

檔案系統中的每個檔案和資料夾都有一個唯一的 絕對路徑 ,即必須開啟才能到達檔案/目錄所在位置的目錄順序,所有路徑用 '/' 連線。上面例子中,指向 file2.ext 的 絕對路徑 是 "dir/subdir2/subsubdir2/file2.ext" 。每個目錄名由字母、數字和/或空格組成,每個檔名遵循 name.extension 的格式,其中 name 和 extension由字母、數字和/或空格組成。

給定一個以上述格式表示檔案系統的字串 input ,返回檔案系統中 指向 檔案 的 最長絕對路徑 的長度 。 如果系統中沒有檔案,返回 0。

示例1

輸入:input = "dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext"
輸出:20
解釋:只有一個檔案,絕對路徑為 "dir/subdir2/file.ext" ,路徑長度 20

示例2

輸入:input = "dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext"
輸出:32
解釋:存在兩個檔案:
"dir/subdir1/file1.ext" ,路徑長度 21
"dir/subdir2/subsubdir2/file2.ext" ,路徑長度 32
返回 32 ,因為這是最長的路徑

題意

題目的輸入給出的是一個字串input,字串中說明存在資料夾名和資料夾名,而資料夾路徑以\n為當前資料夾或檔案為結尾,而\t表示當前資料夾下還有子資料夾。其實我們可以考慮將檔案系統看作一棵樹一個森林,如下圖所示。而我們需要做的是通過遍歷這棵樹或森林找到最大的深度也就是答案最長的路徑。

做法

O(n)模擬, 使用棧來模擬當前操作,棧中儲存的是當前路徑的長度,棧頂元素代表最後一個檔案或資料夾的長度,我們需要開一個sum變數記錄每次模擬遞迴遍歷樹中的一條路徑的長度,我們需要維護一個layer變數記錄當前我們遍歷到第幾個layer了,layer表示的是樹的第幾層(也可以表示為檔案路徑中該路徑的子檔案的層數),當input字串中含有\t, 那麼說明還沒有結尾,layer需要++, 而棧的長度相當於當前路徑的深度也就是層數,如果棧的長度大於當前路徑的深度, 那麼說明該路徑走到底了,需要回溯,將棧中元素彈出。如果走到\n說明到路徑結尾了,我們需要將改路徑push到棧中, 由於最後求的路徑是需要在每一層檔名上加上/, 所以還要加上此操作,最後返回最大長度即可。

class Solution {
public:
    int lengthLongestPath(string input) {
        int res = 0, sum = 0, layer = 0; // res: 表示最長長度, sum記錄當前樹的長度,layer代表層次
        stack<int> st; // 儲存當前路徑的長度
        for (int i = 0; i < input.size(); i ++) {
            layer = 0;
            while (i < input.size() && input[i] == '\t') // 判斷這條路徑有幾層
                i ++, layer ++;
            while (st.size() > layer) //判斷棧中路徑層數大於當前路徑層
                sum -= st.top(), st.pop();
            int j = i; // j: 記錄當前節點檔案的長度
            while (j < input.size() && input[j] != '\n') j ++;
            int len = j - i;
            st.push(len); // len:表示當前檔案的長度
            sum += len;
            // 如果存在.說明有檔案,而題目中要求的是檔案最長路徑
            if (input.substr(i, len).find('.') != -1) {
                res = max(res, sum + (int)st.size() - 1); // st.size() - 1是對每個檔案加上/
            }
            i = j;
        }
        return res;
    }
};