题目描述:
你需要设计一个能提供下面两个函数的文件系统:
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 因为该路径不存在。
提示:
对两个函数的调用次数加起来小于等于 10^4
2 <= path.length <= 100
1 <= value <= 10^9
方法1:
主要思路:解题链接汇总
(1)构建字典树;
(2)将给出的路径先进行分割,得到每一级的结点字符串,若该字符串在字典树中有结点,则接着在字典树中遍历,若没有,则判断当前结点是否是分割路径中的最后一个结点,若是,则生成对应结点,并返回true;否则返回false;
(3)对于get函数,同样将路径先进行分割,判断路径的存在性即可;
struct Node {
unordered_map<string,Node*> next;
int value;
};
class FileSystem {
public:
Node* root;
FileSystem() {
root=new Node();//初始化
}
//将给定的字符串进行分割,获得一个个结点
void split_path(string&path,vector<string>&paths){
int index=0;
for(int i=0;i<path.size();++i){
if(path[i]=='/'){
index=i+1;
while(index<path.size()&&path[index]!='/'){
++index;
}
string str=path.substr(i+1,index-i-1);
if(!str.empty()){
paths.push_back(str);
}
}
i=index-1;
}
}
bool createPath(string path, int value) {
if(path.empty()){
return false;
}
vector<string> paths;
split_path(path,paths);//分割路径
if(paths.empty()){
return false;
}
Node* tmp=root;
for(int i=0;i<paths.size();++i){
if(tmp->next.count(paths[i])==0){
//判读当前结点是否存在
if(i==paths.size()-1){
//若不存在,该该结点是否是最后一个结点
//若是,则生成对应的结点
tmp->next[paths[i]]=new Node();
tmp->next[paths[i]]->value=value;
return true;
}
else{
//否则,返回false
return false;
}
}
else{
//找下一个结点
tmp=tmp->next[paths[i]];
}
}
return false;
}
int get(string path) {
vector<string> paths;
split_path(path,paths);//将给定的字符串进行分割
Node*tmp=root;
for(string&str:paths){
if(tmp->next.count(str)){
tmp=tmp->next[str];
}
else{
//说明路径不存在
return -1;
}
}
return tmp->value;
}
};
/**
* Your FileSystem object will be instantiated and called as such:
* FileSystem* obj = new FileSystem();
* bool param_1 = obj->createPath(path,value);
* int param_2 = obj->get(path);
*/
方法2:
主要思路:
(1)改为go代码
type FileSystem struct {
next map[string]*FileSystem
value int
}
func Constructor() FileSystem {
return FileSystem{
next:make(map[string]*FileSystem),
}
}
func (this *FileSystem) CreatePath(path string, value int) bool {
if len(path)<2 {
return false
}
paths := strings.Split(path,"/")
for i:=1;i<len(paths);i++{
//注意从1开始,第一个是空字符串
if _,ok:=this.next[paths[i]];!ok {
if(i==len(paths)-1){
this.next[paths[i]]=&FileSystem{
next:make(map[string]*FileSystem),
value:value,
}
return true
}else{
return false
}
}else{
this=this.next[paths[i]];
}
}
return false
}
func (this *FileSystem) Get(path string) int {
paths:=strings.Split(path,"/")
for i:=1;i<len(paths);i++ {
if _,ok:=this.next[paths[i]];ok {
this=this.next[paths[i]]
}else{
return -1
}
}
return this.value;
}
/**
* Your FileSystem object will be instantiated and called as such:
* obj := Constructor();
* param_1 := obj.CreatePath(path,value);
* param_2 := obj.Get(path);
*/