Fewest moves to reorder keyed children

Write codeHard35 min

Your task

A UI framework re-renders a list whose children carry keys. old_keys holds the keys of the children currently mounted, in DOM order, and new_keys the keys the next render wants, in order. Keys are unique within each list. The framework turns the old DOM into the new one with three kinds of operation:

  • remove the child for a key that is not in new_keys
  • insert a child for a key that is not in old_keys
  • move a kept child: detach it and re-attach it at any position

Removals and insertions are forced, and inserted children can be placed straight into their final positions, so the only thing worth optimising is moves. Return [removals, insertions, moves], where moves is the smallest number of moves that leaves the kept children in the relative order new_keys gives them. Lists can hold tens of thousands of keys, so aim for O(n log n).

Examples:

  • reconcile_cost(["a", "b", "c", "d"], ["a", "c", "d", "b"]) returns [0, 0, 1]: moving b to the end is enough.
  • reconcile_cost(["a", "b", "c"], ["c", "b", "a"]) returns [0, 0, 2].
  • reconcile_cost(["x", "a", "b", "y"], ["b", "new", "a"]) returns [2, 1, 1]: x and y go, new comes, and one of a and b has to move.

Examples

reconcile_cost(old_keys: list[str], new_keys: list[str]) -> list[int]
Example 1
Inputreconcile_cost(["a", "b", "c", "d"], ["a", "c", "d", "b"])
Output[0, 0, 1]
Example 2
Inputreconcile_cost(["a", "b", "c"], ["c", "b", "a"])
Output[0, 0, 2]
Example 3
Inputreconcile_cost(["x", "a", "b", "y"], ["b", "new", "a"])
Output[2, 1, 1]