Data Structures: Design In-Memory File System
Difficulty: Hard
Problem Statement
Design an in-memory file system to simulate the following functions:
ls(path)
: Ifpath
is a file path, return a list containing only the file’s name. Ifpath
is a directory path, return the list of file and directory names in that directory. The output should be in lexicographic order.mkdir(path)
: Make a new directory according to the givenpath
. The given directory path does not exist. If the parent directory does not exist, create it as well.addContentToFile(filePath, content)
: Writecontent
to the file atfilePath
. If the file does not exist, create it.readContentFromFile(filePath)
: Return the content of the file atfilePath
.
Implementation Details
Implement the following class:
class FileSystem:
def __init__(self):
"""
Initializes the file system.
"""
pass # Your implementation here
def ls(self, path: str) -> List[str]:
"""
List directory contents or file name.
Args:
path (str): The path to the file or directory.
Returns:
List[str]: List of directory or file names in lexicographic order.
"""
pass # Your implementation here
def mkdir(self, path: str) -> None:
"""
Creates a directory at the specified path.
Args:
path (str): The directory path to create.
"""
pass # Your implementation here
def addContentToFile(self, filePath: str, content: str) -> None:
"""
Adds content to a file at the specified path.
Args:
filePath (str): The file path.
content (str): The content to add.
"""
pass # Your implementation here
def readContentFromFile(self, filePath: str) -> str:
"""
Reads content from a file at the specified path.
Args:
filePath (str): The file path.
Returns:
str: The content of the file.
"""
pass # Your implementation here
Constraints
- File Path Lengths: The length of a path or file name is at most 100.
- Content Length: The length of content is at most 50.
- Number of Operations: The number of calls to each function is less than or equal to (10^4).
- Paths: All paths are absolute starting from
'/'
. - Characters: Paths and file names contain lowercase letters, digits,
'/'
, and'.'
.
Example Usage
fs = FileSystem()
print(fs.ls("/")) # Expected Output: []
fs.mkdir("/a/b/c")
fs.addContentToFile("/a/b/c/d", "hello")
print(fs.ls("/")) # Expected Output: ["a"]
print(fs.readContentFromFile("/a/b/c/d")) # Expected Output: "hello"
Test Cases
def test_file_system():
# Test Case 1: Basic directory and file creation
fs = FileSystem()
fs.mkdir("/goowmfn")
print(fs.ls("/goowmfn")) # Expected Output: []
# Test Case 2: Add content to file
fs = FileSystem()
fs.addContentToFile("/a/b/c/d", "hello")
assert fs.readContentFromFile("/a/b/c/d") == "hello"
# Test Case 3: List directory contents
fs = FileSystem()
fs.mkdir("/a/b/c")
fs.addContentToFile("/a/b/c/d", "hello")
assert fs.ls("/a/b") == ["c"]
# Test Case 4: Append content to existing file
fs.addContentToFile("/a/b/c/d", " world")
assert fs.readContentFromFile("/a/b/c/d") == "hello world"
# Test Case 5: List root directory
assert fs.ls("/") == ["a"]
print("All test cases pass!")
Expected Solution Approach
Implement a hierarchical tree structure to represent directories and files.
Algorithm Steps
-
Design Data Structures:
- Use a
Trie
or nested dictionaries to represent directories and files. - Each node represents a directory or a file.
- A directory node contains a mapping of names to child nodes.
- A file node contains content.
- Use a
-
Implement Functions:
-
ls(path)
:- Traverse to the node at the given path.
- If it’s a file, return its name in a list.
- If it’s a directory, return sorted list of its children’s names.
-
mkdir(path)
:- Split the path by
'/'
. - Traverse or create nodes for each directory in the path.
- Split the path by
-
addContentToFile(filePath, content)
:- Traverse or create nodes for each directory in the path.
- For the file node, append content.
-
readContentFromFile(filePath)
:- Traverse to the file node and return its content.
-
-
Edge Cases:
- Handle paths with multiple consecutive
'/'
. - Ensure that file names and directory names are correctly distinguished.
- Handle paths with multiple consecutive
Time Complexity
ls
: (O(L + K \log K)), where (L) is the length of the path, and (K) is the number of entries in the directory.mkdir
andaddContentToFile
: (O(L)), where (L) is the length of the path.readContentFromFile
: (O(L)).
Implementation Hint
Here’s a skeleton to help you start:
class Node:
def __init__(self):
self.children = {}
self.content = ""
class FileSystem:
def __init__(self):
self.root = Node()
def ls(self, path: str) -> List[str]:
node = self.root
if path != "/":
parts = path.split('/')[1:]
for part in parts:
node = node.children[part]
if node.content:
return [part]
return sorted(node.children.keys())
def mkdir(self, path: str) -> None:
node = self.root
parts = path.split('/')[1:]
for part in parts:
if part not in node.children:
node.children[part] = Node()
node = node.children[part]
def addContentToFile(self, filePath: str, content: str) -> None:
node = self.root
parts = filePath.split('/')[1:]
for part in parts[:-1]:
if part not in node.children:
node.children[part] = Node()
node = node.children[part]
file_name = parts[-1]
if file_name not in node.children:
node.children[file_name] = Node()
node.children[file_name].content += content
def readContentFromFile(self, filePath: str) -> str:
node = self.root
parts = filePath.split('/')[1:]
for part in parts:
node = node.children[part]
return node.content
Learning Objectives
-
Implement Hierarchical Data Structures:
- Design tree structures to represent file systems.
- Manage nodes representing both files and directories.
-
Efficient Path Parsing:
- Handle absolute paths correctly.
- Split and process paths efficiently.
-
Data Encapsulation:
- Encapsulate data and functionality within classes.
- Use helper classes or structures when appropriate.
-
Edge Case Handling:
- Manage cases where directories or files do not exist.
- Ensure correct behavior for root and nested paths.
Real-World Applications
- Operating Systems: Simulate file system operations for testing or embedded systems.
- Virtual File Systems: Implement file systems over network protocols or in-memory for applications.
- Cloud Storage Services: Manage user files and directories in services like Dropbox or Google Drive.
- Educational Tools: Teach concepts of file systems and data structures.