You are implementing a simplified document layer for a design tool. The document is a map from string key to string value.
Implement a data structure that supports these operations:
-
apply(key, value)
: immediately update the document so that
document[key] = value
.
-
batch()
: close the current batch of changes. All
apply
calls since the previous
batch()
belong to one undoable unit.
-
undo()
: revert the most recently closed batch.
-
redo()
: reapply the most recently undone batch.
Use standard undo/redo semantics:
-
apply()
takes effect immediately.
-
A batch may contain multiple
apply()
calls.
-
undo()
reverts the entire last batch at once.
-
redo()
reapplies the same batch.
-
If a new batch is created after an
undo()
, the redo history is cleared.
The main requirement is memory efficiency. If the same key is updated multiple times within one batch, you should not store every intermediate change. Instead, the memory used by one batch should be proportional to the number of distinct keys changed in that batch, not the total number of apply() calls.
Example:
-
Initial document:
{ "color": "red" }
-
apply("color", "yellow")
-
apply("color", "pink")
-
batch()
-
undo()
should restore the document to
{ "color": "red" }
-
redo()
should change it back to
{ "color": "pink" }
Also handle keys that did not exist before the batch. If a batch creates a new key, then undo() should remove that key entirely.
Design the data structures and implement these operations. Discuss the time and space complexity.