Problem description:

Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.

k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.

Example:

Given this linked list: 1->2->3->4->5

For k = 2, you should return: 2->1->4->3->5

For k = 3, you should return: 3->2->1->4->5

Note:

Only constant extra memory is allowed.
You may not alter the values in the list’s nodes, only nodes itself may be changed.

Solution:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1st k-1 loop init:
-1 -> 1 -> 2 -> 3 -> 4 -> 5
| | |
pre cur nex

-1 -> 2 -> 1 -> 3 -> 4 -> 5
| | |
pre cur nex

-1 -> 3 -> 2 -> 1 -> 4 -> 5
| | |
pre cur nex


2nd loop init:
-1 -> 3 -> 2 -> 1 -> 4 -> 5
| | |
pre cur nex

Above is how it works inside one group iteration(for example, k=3)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
if(!head || k == 1) return head;
ListNode *dummy= new ListNode(-1); dummy->next= head;
ListNode *cur= dummy, *nex, *pre= dummy;

//1. get the length of linked list
int count= 0;
while(cur= cur->next)
count++;

//2. use the length to do swapping
while(count >= k){
cur= pre->next;
nex= cur->next;
for(int i= 1; i< k; i++){ //IMPORTANT: change in k groups, only needs to swap k-1 times
cur->next= nex->next;
nex->next= pre->next;
pre->next= nex;
nex= cur->next;
}
pre= cur;
count -= k;
}
return dummy->next;
}
};

time complexity: $O(n)$
space complexity: $O(1)$
reference:
https://goo.gl/uyufCT