设计文件系统

https://leetcode-cn.com/problems/design-file-system/

1166. 设计文件系统

你需要设计一个能提供下面两个函数的文件系统:

create(path, value): 创建一个新的路径,并尽可能将值 value 与路径 path 关联,然后返回 True。如果路径已经存在或者路径的父路径不存在,则返回 False。
get(path): 返回与路径关联的值。如果路径不存在,则返回 -1。
“路径” 是由一个或多个符合下述格式的字符串连接起来形成的:在 / 后跟着一个或多个小写英文字母。

例如 /leetcode 和 /leetcode/problems 都是有效的路径,但空字符串和 / 不是有效的路径。

好了,接下来就请你来实现这两个函数吧!(请参考示例以获得更多信息)

 

示例 1:

输入:
["FileSystem","create","get"]
[[],["/a",1],["/a"]]
输出:
[null,true,1]
解释:
FileSystem fileSystem = new FileSystem();

fileSystem.create("/a", 1); // 返回 true
fileSystem.get("/a"); // 返回 1
示例 2:

输入:
["FileSystem","create","create","get","create","get"]
[[],["/leet",1],["/leet/code",2],["/leet/code"],["/c/d",1],["/c"]]
输出:
[null,true,true,2,false,-1]
解释:
FileSystem fileSystem = new FileSystem();

fileSystem.create("/leet", 1); // 返回 true
fileSystem.create("/leet/code", 2); // 返回 true
fileSystem.get("/leet/code"); // 返回 2
fileSystem.create("/c/d", 1); // 返回 false 因为父路径 "/c" 不存在。
fileSystem.get("/c"); // 返回 -1 因为该路径不存在。

错误解法:

class FileSystem {
public:
    FileSystem() {

    }
    
    bool createPath(string path, int value) {
        // 路径合法
        if (!isLegualPath(path)) return false;
        // 路径是否存在
        auto tmp = m_pool.find(path);
        if (tmp != m_pool.end()) return false;
        
        //插入
        m_pool.insert(make_pair(path, value));
        return true;
    }
    
    int get(string path) {
        // 路径合法
        if (!isLegualPath(path)) return false;
        // 路径是否存在
        auto tmp = m_pool.find(path);
        if (tmp != m_pool.end()) return tmp->second;
        return -1;
    }
    
    bool isLegualPath(string path)
    {
        bool ret = false;
        // '/'开头,后面至少一个小写字母
        int pos = 0;
        while(path.substr(pos, path.size()-1).find('/') != std::string::npos)
        {
            ret = true;
            if (path[pos+1] < 'a' || path[pos+1] > 'z') {
                return false;
            }
            pos = pos + 1;
        }
        return ret;
    }
    
    //存储路径
    map<string, int> m_pool;
};

花了太多时间在保证输入合法性上,其实这只是次要的。而且对于第二个用例就不过了。

 

看了一个很高效的解法:

class FileSystem {
public:
    FileSystem() = default;
    
    bool createPath(string path, int value) {
        if (path == "/" || path.empty()) {
            return false;
        }
        auto pos = path.rfind("/");
        if (pos == std::string::npos) {
            return false;
        }
        if (pos != 0) {  // 说明不只有一个 '/' 
            auto prefix = path.substr(0, pos);
            if (paths_.find(prefix) == paths_.end()) {
                return false;
            }
        }
        return paths_.insert(make_pair(path, value));
    }
    
    int get(string path) {
        auto iter = paths_.find(path);
        if (iter == paths_.end()) {
            return -1;
        }
        return iter->second;
    }

private:
    std::map<std::string, int> paths_;
};

其中,使用了rfind() 从后向前搜索,巧妙的解决了后面子目录依赖前面目录是否存在的问题。

posted @ 2020-03-09 19:32  ren_zhg1992  阅读(489)  评论(0)    收藏  举报