Solution: The Circularly Linked List

In Chapter 6, we ran head.next.next.next.next = head, pointing the last node of a list back at its head, and we said that this creates a circular linked list.

   ┌───┐      ┌───┐      ┌───┐      ┌───┐
┌▶ │ 0 │ ──▶  │ 1 │ ──▶  │ 2 │ ──▶  │ 3 │ ─┐
│  └───┘      └───┘      └───┘      └───┘  │
└──────────────────────────────────────────┘

Then, in the Chapter 6 practice, we wrote an algorithm to detect whether a linked list contains a cycle. In both cases, we did not use the cycle for anything. In the first, it was just something we could build with links. In the second, it was a bug that would make a traversal run forever. For the Josephus problem, we actually want a cycle, since the people in the game stand in a circle.

We need two operations for the Josephus problem.

The first is moving around the circle. To move one position, follow the link: current = current.next. Suppose current is at node 0:

   ┌───┐      ┌───┐      ┌───┐      ┌───┐
┌▶ │ 0 │ ──▶  │ 1 │ ──▶  │ 2 │ ──▶  │ 3 │ ─┐
│  └───┘      └───┘      └───┘      └───┘  │
│    ▲                                     │
│    │                                     │
│ current                                  │
└──────────────────────────────────────────┘

After current = current.next, it is at node 1:

   ┌───┐      ┌───┐      ┌───┐      ┌───┐
┌▶ │ 0 │ ──▶  │ 1 │ ──▶  │ 2 │ ──▶  │ 3 │ ─┐
│  └───┘      └───┘      └───┘      └───┘  │
│               ▲                          │
│               │                          │
│            current                       │
└──────────────────────────────────────────┘

Notice that the nodes stay where they are, and only our reference changes.

The second is removing a node. To remove the node after current, link around it:

current.next = current.next.next;  // unlink the node after current

Continuing from the picture above, current is at node 1, so this removes node 2:

   ┌───┐      ┌───┐                 ┌───┐
┌▶ │ 0 │ ──▶  │ 1 │ ─────────────▶  │ 3 │ ─┐
│  └───┘      └───┘                 └───┘  │
│               ▲                          │
│               │                          │
│            current                       │
└──────────────────────────────────────────┘

                         ┌───┐
                         │ 2 │   (no longer linked)
                         └───┘

This is one assignment, so it is . Note that this removes the node after current, not current itself. Each node stores only a next reference, so to remove a node we need a reference to the node before it.

How do we traverse a circle? In an ordinary linked list, we follow links until we reach null. Here, nothing is ever null, so a loop that stops at null will run forever. Instead, we remember where we started and stop when we return to that node:

Node walker = current;
do {
  System.out.println(walker.value);
  walker = walker.next;
} while (walker != current);

We use a do-while loop because the check must come after the visit: at the start, walker == current is already true, so a regular while loop would end before visiting any node.