25 reverse nodes in k groups
题目链接
题意
给一个链表和一个数字k,要求从链表头开始,每次翻转k个节点,若不足k个节点则不翻转
思路
用一个节点指针currentHead指向每次要翻转的k个节点的第一个,另一个节点指针boundary用于向后搜索到要翻转的k个节点后的第一个节点,然后进行k次操作,每次操作中先用temp保存待翻转的第二个节点指针,然后使第一个节点指针的next指向boundary,这就实现了将头节点放到待翻转区域的尾部了,接着表示将待翻转区域的boundary指针指向刚移动的第一个节点指针currentHead,最后将temp赋值给currentHead,也就是将原本的第二个节点指针变成了第一个,如此循环。算法复杂度为O(n)。
递归版本
ListNode* reverseKGroup(ListNode* head, int k) {
if (k == 1)
return head;
ListNode *boundary = head, *temp;
int count = 0;
while (boundary&&count < k) {
boundary = boundary->next;
++count;
}
if (count == k) {
boundary = reverseKGroup(boundary, k);
while (count--) {
temp = head->next;
head->next = boundary;
boundary = head;
head = temp;
}
head = boundary;
}
return head;
}
非递归版本
/**
*比递归版本快了。。1ms
*/
ListNode* reverseKGroup(ListNode* head, int k) {
if (k == 1)
return head;
ListNode *currentHead = head, *boundary = head,
*theNodeToMove, *temp, *lastOfLastKNodes = nullptr, *last;
int count;
bool firstTurn = true;
while (boundary) {
boundary = currentHead;
count = 0;
//用指针boundary找到需要翻转的k个节点之后的第一个节点
while (boundary&&count < k) {
boundary = boundary->next;
++count;
}
if (count == k) {
last = currentHead;//先保存当前第一个节点指针,后面用于更新lastOfLastKNodes
theNodeToMove = currentHead;
currentHead = boundary;
while (count--) {
temp = theNodeToMove->next;
theNodeToMove->next = boundary;
boundary = theNodeToMove;
theNodeToMove = temp;
}
if (firstTurn) {//第一遍循环
firstTurn = false;
head = boundary;
lastOfLastKNodes = last;
}
else {
lastOfLastKNodes->next = boundary;
lastOfLastKNodes = last;
}
}
}
return head;
}
难点
- k个节点指针翻转时循环k次
- 非递归版本需要每次翻转完k个节点后需要用lastOfLastKNodes记录翻转后的最后一个节点,也就未翻转时的第一个节点currentHead,如果是第一遍循环只需记录,否则必须先将已有的lastOfLastKNodes的next指向本次翻转后的第一个节点,然后再改变lastOfLastKNodes的值