题目
题目描述:
给定一个文件系统目录结构,该结构以字符串数组的形式表示,每个字符串表示一个文件或目录的路径。你需要删除指定的目录,并返回删除后的目录结构。如果目录不存在或目录不为空,则无需删除并返回原始目录结构。
输入:
- paths: 一个字符串数组,表示文件系统的目录结构。
- dir: 需要删除的目录路径。
输出:
- 删除指定目录后的文件系统目录结构,如果目录不存在或不为空,则返回原始目录结构。
示例:
输入:
paths = ["a/","a/b/","c/d/","c/d/e/","c/f/"]
dir = "a/b/"
输出:
["a/","c/d/","c/d/e/","c/f/"]
输入:
paths = ["a/","a/b/","c/d/","c/d/e/","c/f/"]
dir = "c/d/"
输出:
["a/","a/b/"]
思路
- 构建目录树:首先,我们需要将输入的路径数组转换为一个目录树结构,以便能够方便地判断目录是否存在以及是否为空。
- 检查目录:检查需要删除的目录是否存在以及是否为空。
- 删除目录:如果目录存在且为空,则删除该目录及其父目录中的引用。
- 重建路径数组:根据修改后的目录树结构,重新生成路径数组。
Java 编码解析
import java.util.*;
class Solution {
public List<String> removeDirectory(String[] paths, String dir) {
Map<String, List<String>> tree = new HashMap<>();
List<String> result = new ArrayList<>();
// 构建目录树
for (String path : paths) {
String[] nodes = path.split("/");
Map<String, List<String>> current = tree;
for (int i = 1; i < nodes.length; i++) {
String node = nodes[i];
current.putIfAbsent(node, new ArrayList<>());
current = current.get(node);
}
// 标记叶子节点
current.put("", new ArrayList<>());
}
// 检查并删除目录
boolean found = removeFromTree(tree, dir.split("/"), 1);
// 重建路径数组
buildPaths(tree, "", result);
return found && !result.contains(dir + "/") ? result : Arrays.asList(paths);
}
private boolean removeFromTree(Map<String, List<String>> tree, String[] dir, int index) {
if (index == dir.length) {
// 到达目标目录
List<String> children = tree.get(dir[index - 1]);
return children != null && children.isEmpty();
}
String key = dir[index];
List<String> children = tree.get(key);
if (children == null) {
return false;
}
boolean found = false;
Iterator<Map.Entry<String, List<String>>> iterator = children.iterator();
while (iterator.hasNext()) {
Map.Entry<String, List<String>> entry = iterator.next();
if (removeFromTree(entry.getValue(), dir, index + 1)) {
found = true;
if (entry.getValue().isEmpty()) {
iterator.remove();
}
}
}
if (children.isEmpty()) {
tree.remove(key);
return true;
}
return found;
}
private void buildPaths(Map<String, List<String>> tree, String prefix, List<String> result) {
for (Map.Entry<String, List<String>> entry : tree.entrySet()) {
String newPrefix = prefix.isEmpty() ? entry.getKey() : prefix + "/" + entry.getKey();
result.add(newPrefix + "/");
if (!entry.getValue().isEmpty() && !entry.getValue().containsKey("")) {
buildPaths(entry.getValue(), newPrefix, result);
}
}
}
}
C++ 编码解析
#include <iostream>
#include <vector>
#include <unordered_map>
#include <string>
using namespace std;
class Solution {
public:
vector<string> removeDirectory(vector<string>& paths, string dir) {
unordered_map<string, unordered_map<string, bool>> tree;
vector<string> result;
// 构建目录树
for (const string& path : paths) {
string current = "/";
size_t pos = 0;
while ((pos = path.find("/", pos)) != string::npos) {
string node = path.substr(0, pos);
tree[current][node] = false;
current = node + "/";
pos++;
}
tree[current][""] = true; // 标记叶子节点
}
// 检查并删除目录
bool found = removeFromTree(tree, dir, 1);
// 重建路径数组
buildPaths(tree, "/", result);
return found && find(result.begin(), result.end(), dir + "/") == result.end() ? result : paths;
}
private:
bool removeFromTree(unordered_map<string, unordered_map<string, bool>>& tree, const vector<string>& dir, int index) {
if (index == dir.size()) {
auto it = tree.find("/");
if (it == tree.end()) return false;
auto childIt = it->second.find(dir[index - 1]);
return childIt != it->second.end() && childIt->second.empty();
}
string key = dir[index];
auto it = tree.find("/");
if (it == tree.end() || it->second.find(key) == it->second.end()) {
return false;
}
bool found = false;
for (auto& pair : it->second[key]) {
if (removeFromTree(pair.second, dir, index + 1)) {
found = true;
if (pair.second.empty()) {
it->second.erase(key);
break;
}
}
}
return found;
}
void buildPaths(unordered_map<string, unordered_map<string, bool>>& tree, string prefix, vector<string>& result) {
auto it = tree.find(prefix);
if (it != tree.end()) {
result.push_back(prefix);
for (const auto& pair : it->second) {
if (!pair.second.empty() || pair.first.empty()) {
buildPaths(pair.second, prefix + pair.first, result);
}
}
}
}
};
Python 编码解析
class Solution:
def removeDirectory(self, paths: List[str], dir: str) -> List[str]:
tree = {}
result = []
# 构建目录树
for path in paths:
nodes = path.split("/")
current = tree
for i in range(1, len(nodes)):
node = nodes[i]
if node not in current:
current[node] = {}
current = current[node]
# 标记叶子节点
current[""] = True
# 检查并删除目录
found = self.removeFromTree(tree, dir.split("/"), 1)
# 重建路径数组
self.buildPaths(tree, "", result)
return result if found and dir + "/" not in result else paths
def removeFromTree(self, tree, dir, index):
if index == len(dir):
node = dir[-1]
children = tree.get(node, {})
return "" in children and not children.keys() - {""}
node = dir[index]
children = tree.get(node, {})
found = False
keys_to_remove = []
for key, sub_tree in children.items():
if self.removeFromTree(sub_tree, dir, index + 1):
found = True
if not sub_tree:
keys_to_remove.append(key)
for key in keys_to_remove:
del children[key]