Trace

LinkedList<T> is doubly linked: it keeps head, tail, and size, and every node links to both its predecessor and its successor.

Solution

After add(10), size 1:

          ┌────┐
head ───▶ │ 10 │ ◀─── tail
          └────┘

After add(20), size 2:

          ┌────┐      ┌────┐
head ───▶ │ 10 │ ◀──▶ │ 20 │ ◀─── tail
          └────┘      └────┘

After add(30), size 3:

          ┌────┐      ┌────┐      ┌────┐
head ───▶ │ 10 │ ◀──▶ │ 20 │ ◀──▶ │ 30 │ ◀─── tail
          └────┘      └────┘      └────┘

After remove(0) (removes the node holding 10; it is the head with no predecessor, so head moves to the node holding 20), size 2:

          ┌────┐      ┌────┐
head ───▶ │ 20 │ ◀──▶ │ 30 │ ◀─── tail
          └────┘      └────┘

After add(40), size 3:

          ┌────┐      ┌────┐      ┌────┐
head ───▶ │ 20 │ ◀──▶ │ 30 │ ◀──▶ │ 40 │ ◀─── tail
          └────┘      └────┘      └────┘

After remove(1) (index 1 is the node holding 30, which has a real node on both sides, so the two-line unlink applies with no guard), size 2:

          ┌────┐      ┌────┐
head ───▶ │ 20 │ ◀──▶ │ 40 │ ◀─── tail
          └────┘      └────┘