public static <T> void remove_kth_last(Ref<node_t<T>> L, int k) {
    // Advances k steps first.
    node_t<T> ahead = L.value;
    int num = k;
    while (ahead != null && num != 0) {
      ahead = ahead.next;
      --num;
    }

    if (num != 0) {
      throw new IllegalArgumentException("not enough nodes in the list");
    }

    node_t<T> pre = null, curr = L.value;
    // Finds the k-th last node.
    while (ahead != null) {
      pre = curr;
      curr = curr.next; ahead = ahead.next;
    }
    if (pre != null) {
      pre.next = curr.next;
    } else {
      L.value = curr.next;  // special case: delete L.
    }
  }