~/problems / Linked lists / LRU / LFU cache

Recent files menu

easy ~15 min

A text editor's File → Open Recent menu remembers at most capacity paths, most recently opened first. Build it as class RecentFiles:

  • RecentFiles(capacity): an empty menu that holds at most capacity paths (capacity >= 1).
  • open(path) -> str | None: the user opened path. It moves to the top of the menu (added if new, moved if already listed). If the menu now has more than capacity paths, drop the least recently opened one and return it; otherwise return None.
  • forget(path) -> bool: the file was deleted, so remove path from the menu wherever it is. Return True if it was listed, False if it wasn't.
  • menu() -> list[str]: all listed paths, most recent first (O(n) is fine here; the tests use it to check your order).
r = RecentFiles(3)
r.open("a.txt"); r.open("b.txt"); r.open("c.txt")   # all return None
r.open("a.txt")      # None: already listed, just moves to the top
r.menu()             # ["a.txt", "c.txt", "b.txt"]
r.open("d.txt")      # "b.txt" is dropped and returned
r.forget("c.txt")    # True
r.forget("c.txt")    # False
r.menu()             # ["d.txt", "a.txt"]

open and forget must be O(1). The tests make 200,000 calls on a menu of 50,000 paths, so removing from the middle of a Python list is too slow. Build it the way the Basics drill did: a dict from path to node plus a doubly linked list with sentinel head and tail. (Don't use OrderedDict; the point is to write the list.)

Show hint

forget is the new part: look up the node in the dict, unlink it by joining its prev and next to each other, and delete the dict entry. open is "unlink if present, push to the front, and if too big unlink tail.prev".

Topic: LRU / LFU cache. Hash map + doubly linked list for O(1) get/put.

Read the visual guide
0:00
Ctrl ' run · Ctrl ↵ submit
esc