The basic idea is for each step,we set the the node after `head`

as the list's new head, so that `head`

then is `tail`

. After reversing k nodes, we update the references and iterate through the whole list. If the size of the list is a multiple of k, the list is safely returned. Otherwise, a recursive call is made on the left-out nodes to undo the reverse. So the whole iteration times will be `(n + n%k)`

Here is an example of how it works(case of K = 3):

Initial:

```
sentinel -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 ->...
| | |
dummy tail newHead
```

Set the node after tail @newHead as the new head. And the list:

```
sentinel -> 2 -> 1 -> 3 -> 4 -> 5 -> 6 ->...
| | |
dummy tail newHead
```

Set node after tail as new Head:

```
sentinel -> 3 -> 2 -> 1 -> 4 -> 5 -> 6 ->...
| |
dummy tail
```

3 nodes are reversed. Update the references:

```
sentinel -> 3 -> 2 -> 1 -> 4 -> 5 -> 6 ->...
| | |
dummy tail newHead
```

Here is code:

```
public ListNode reverseKGroup(ListNode head, int k) {
if (k < 2 || head == null) return head;
ListNode sentinel = new ListNode(0);
sentinel.next = head;
ListNode dummy = sentinel, tail = head, newHead;
While (true) {
int count = k - 1;
while (count > 0) {
if (tail.next != null) {
newHead = tail.next;
tail.next = newHead.next;
newHead.next = dummy.next;
dummy.next = newHead;
count--;
} else {
/// list size is not multiple of k, a recursive call on the left-out nodes to undo the reverse
dummy.next = reverseKGroup(dummy.next, k - count);
return sentinel.next;
}
}
if (tail.next == null) return sentinel.next; /// list size is multiple of k, safely return
dummy = tail;
tail = tail.next;
}
}
```