Build an In-Memory File Vault with Duplicate-Name Handling
HarveySoftware Engineer · OnsiteLast updated
Design an in-memory hierarchical file vault supporting automatic directory creation, lexicographical directory listings, and duplicate-name resolution using the smallest available numeric suffix.
Problem Statement
Implement an in-memory hierarchical file vault that manages files and directories. The vault must automatically create any missing intermediate directories when a file is added. If a file with the target name already exists in the destination directory, the vault must resolve the collision by finding the smallest positive integer k >= 1 such that appending (k) to the base name produces an unused filename.
Implement the FileVault class:
FileVault(): Initializes the vault with an empty root directory/.add_file(path: str) -> str: Inserts a file at the given absolute path, creating any missing parent directories along the way. Returns the final absolute path of the created file after resolving any name collisions.list_dir(path: str) -> list[str]: Returns a list of all immediate child entries (both subdirectories and files) directly located inpath, sorted in lexicographical order (ASCII). Ifpathdoes not exist or refers to a file, return an empty list.
Name Collision & Extension Rules
For a target filename:
- If a dot
.exists at an index greater than 0, the extension is defined as everything from the last.to the end, and the base name is everything preceding it (e.g.,"archive.tar.gz"has base"archive.tar"and extension".gz"). - If there is no dot, or if the only dot is at index 0 (e.g.,
".env"), the extension is empty""and the base name is the entire filename. - If the resolved target filename already exists in the target directory, format candidate names as
f"{base} ({k}){ext}"fork = 1, 2, 3, ...and assign the first available name.
Interface
class FileVault:
def __init__(self):
pass
def add_file(self, path: str) -> str:
pass
def list_dir(self, path: str) -> list[str]:
pass
Constraints
- All paths are absolute paths starting with
/. - Paths contain valid ASCII characters, without consecutive slashes (e.g.,
//) or trailing slashes (except the root/). - Total operations across
add_fileandlist_dirwill not exceed10,000. - Directory and file names do not contain
/. - A file and directory will not share the exact same name within the same parent directory.
Examples
Example 1
vault = FileVault()
vault.add_file("/docs/report.pdf")
# Returns: "/docs/report.pdf"
vault.add_file("/docs/report.pdf")
# Returns: "/docs/report (1).pdf"
vault.add_file("/docs/report.pdf")
# Returns: "/docs/report (2).pdf"
vault.list_dir("/docs")
# Returns: ["report (1).pdf", "report (2).pdf", "report.pdf"]
Example 2
vault = FileVault()
vault.add_file("/home/.bashrc")
# Returns: "/home/.bashrc"
vault.add_file("/home/.bashrc")
# Returns: "/home/.bashrc (1)"
vault.add_file("/home/notes (2).txt")
# Returns: "/home/notes (2).txt"
vault.add_file("/home/notes.txt")
# Returns: "/home/notes.txt"
vault.add_file("/home/notes.txt")
# Returns: "/home/notes (1).txt" (smallest available k >= 1)
vault.list_dir("/home")
# Returns: [".bashrc", ".bashrc (1)", "notes (1).txt", "notes (2).txt", "notes.txt"]
Hints
Hint 1
Model the filesystem as a tree of directory nodes, where each node stores a set/map of child directories and a set/map of files.
Hint 2
Be careful when splitting the filename into base and extension: find the last occurrence of '.' and only treat it as an extension delimiter if its index is strictly greater than 0.
Hint 3
To find the smallest available suffix, check `k = 1, 2, ...` against a hash set of existing names in that specific directory until an unused name is found.
Follow-up questions
- How would you optimize the search for the smallest `k` if there are millions of duplicate additions for the same base name?
- How would your design change if you needed to support moving or renaming directories (`mv /a /b`) efficiently without rebuilding entire paths?
- How would you make this file vault thread-safe for concurrent read and write operations without creating a global lock bottleneck?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.