[LeetCode] Design In-Memory File System 設計內存文件系統


 

Design an in-memory file system to simulate the following functions:

ls: Given a path in string format. If it is a file path, return a list that only contains this file's name. If it is a directory path, return the list of file and directory names in this directory. Your output (file and directory names together) should in lexicographic order.

mkdir: Given a directory path that does not exist, you should make a new directory according to the path. If the middle directories in the path don't exist either, you should create them as well. This function has void return type.

addContentToFile: Given a file path and file content in string format. If the file doesn't exist, you need to create that file containing given content. If the file already exists, you need to append given content to original content. This function has void return type.

readContentFromFile: Given a file path, return its content in string format.

Example:

Input: 
["FileSystem","ls","mkdir","addContentToFile","ls","readContentFromFile"]
[[],["/"],["/a/b/c"],["/a/b/c/d","hello"],["/"],["/a/b/c/d"]]
Output:
[null,[],null,null,["a"],"hello"]
Explanation:

filesystem

 

Note:

  1. You can assume all file or directory paths are absolute paths which begin with / and do not end with /except that the path is just "/".
  2. You can assume that all operations will be passed valid parameters and users will not attempt to retrieve file content or list a directory or file that does not exist.
  3. You can assume that all directory names and file names only contain lower-case letters, and same names won't exist in the same directory.

 

這道題讓我們設計一個內存文件系統,實現顯示當前文件,創建文件,添加內容到文件,讀取文件內容等功能,感覺像是模擬一個terminal的一些命令。這道題比較tricky的地方是ls這個命令,題目中的例子其實不能很好的展示出ls的要求,其對文件和文件夾的處理方式是不同的。由於這里面的文件沒有后綴,所以最后一個字符串有可能是文件,也有可能是文件夾。比如a/b/c,那么最后的c有可能是文件夾,也有可能好是文件,如果c是文件夾的話,ls命令要輸出文件夾c中的所有文件和文件夾,而當c是文件的話,只需要輸出文件c即可。另外需要注意的是在創建文件夾的時候,路徑上沒有的文件夾都要創建出來,還有就是在給文件添加內容時,路徑中沒有的文件夾都要創建出來。論壇上這道題的高票解法都新建了一個自定義類,但是博主一般不喜歡用自定義類來解題,而且感覺那些使用了自定義類的解法並沒有更簡潔易懂,所以這里博主就不創建自定義類了,而是使用兩個哈希表來做,其中dirs建立了路徑和其對應的包含所有文件和文件夾的集合之間的映射,files建立了文件的路徑跟其內容之間的映射。

最開始時將根目錄"/"放入dirs中,然后看ls的實現方法,如果該路徑存在於files中,說明最后一個字符串是文件,那么我們將文件名取出來返回即可,如果不存在,說明最后一個字符串是文件夾,那么我們到dirs中取出該文件夾內所有的東西返回即可。再來看mkdir函數,我們的處理方法就是根據"/"來分隔分隔字符串,如果是Java,那么直接用String自帶的split函數就好了,但是C++沒有Java那么多自帶函數,所以只能借助字符串流類來處理,處理方法就是將每一層的路徑分離出來,然后將該層的文件或者文件夾加入對應的集合中,注意的地方就是處理根目錄時,要先加上"/",其他情況都是后加。下面來看addContentToFile函數,首先分離出路徑和文件名,如果路徑為空,說明是根目錄,需要加上"/",然后看這個路徑是否已經在dirs中存在,如果不存在,調用mkdir來創建該路徑,然后把文件加入該路徑對應的集合中,再把內容加入該文件路徑的映射中。最后的讀取文件內容就相當簡單了,直接在files中返回即可,參見代碼如下:

 

class FileSystem {
public:
    FileSystem() {
        dirs["/"];
    }
    
    vector<string> ls(string path) {
        if (files.count(path)) {
            int idx = path.find_last_of('/');
            return {path.substr(idx + 1)};
        }
        auto t = dirs[path];
        return vector<string>(t.begin(), t.end());
    }
    
    void mkdir(string path) {
        istringstream is(path);
        string t = "", dir = "";
        while (getline(is, t, '/')) {
            if (t.empty()) continue;
            if (dir.empty()) dir += "/";
            dirs[dir].insert(t);
            if (dir.size() > 1) dir += "/";
            dir += t;
        }
    }
    
    void addContentToFile(string filePath, string content) {
        int idx = filePath.find_last_of('/');
        string dir = filePath.substr(0, idx);
        string file = filePath.substr(idx + 1);
        if (dir.empty()) dir = "/";
        if (!dirs.count(dir)) mkdir(dir);
        dirs[dir].insert(file);
        files[filePath].append(content);
    }
    
    string readContentFromFile(string filePath) {
        return files[filePath];
    }
    
private:
    unordered_map<string, set<string>> dirs;
    unordered_map<string, string> files;
};

 

類似題目:

LRU Cache

LFU Cache 

 

參考資料:

https://discuss.leetcode.com/topic/90250/c-fast-no-user-defined-types-needed

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM