Level 1 Files and extensions
You're writing the index behind a desktop file finder. Implement FileFinder, which starts empty.
A path looks like "/docs/2024/report.pdf": it starts with /, and its parts are separated by /. The last part is the file's name. A file's extension is everything after the last . in its name, or "" if the name has no . at all (so "a.tar.gz" has extension "gz", ".bashrc" has "bashrc", "Makefile" and "odd." both have ""). Extensions are case-sensitive.
add_file(path: str, size: int) -> bool: add a file.False(changing nothing) if that path is already in the index.remove_file(path: str) -> bool: remove it.Falseif it isn't there.get_size(path: str) -> int | None: its size, orNoneif it isn't there.find_by_extension(extension: str) -> list[str]: the paths of all files with exactly that extension, sorted alphabetically.
ff = FileFinder()
ff.add_file("/docs/report.pdf", 1200) # True
ff.add_file("/docs/notes.txt", 300) # True
ff.add_file("/todo.txt", 20) # True
ff.add_file("/todo.txt", 99) # False: already there
ff.get_size("/todo.txt") # 20
ff.find_by_extension("txt") # ["/docs/notes.txt", "/todo.txt"]
ff.remove_file("/docs/notes.txt") # True
ff.find_by_extension("txt") # ["/todo.txt"]
ff.get_size("/docs/notes.txt") # None
Constraints
- Up to
5 * 10^4files and as many calls. Paths are at most 100 characters of letters, digits,.,_,-and/. 0 <= size <= 10^12.
find_by_extension is called about as often as files are added, so it shouldn't look at every file: aim for O(k log k) where k is the number of files it returns.
Show hint
Keep a second map, from extension to the set of paths that have it, and update it on every add and remove.