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.
You may not alter the values in the nodes, only nodes itself may be changed.
Only constant memory is allowed.
For 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
题目的难度在于翻转的长度不再是整个链表的长度了。在确定反转长度的情况下仍然可以利用链表的reverse,用1-2-3-4-5为例,首先反转两个变成2-1-3-4-5,下一次应该反转3和4,利用reverse仍然可以实现,但要注意的是,反转后的顺序4-3,其中的4必须与前面1联系,而3必须与后面的3联系,否则整个链表就断了。另外,最后只剩下一个5时,其长度已经小于要求的长度2了,这时候应该返回NULL,代表与前面的关系不改变。
首先给出改进的reverse函数,其中head表示当前要反转的链表段的起始位置,n-1表示还剩有多少个数没有完成反转,tail表示这段要反转链表反转后的尾部(其实就是反转前此段链表的头部),begin表示此段链表的前一个结点,在完成反转后必须与前一个结点保持联系。
ListNode* reverse(ListNode* head,int n,ListNode* tail,ListNode* begin){ if(head&&!head->next&&n>1)return NULL; if(n==1){ if(head&&tail)tail->next=head->next; if(begin)begin->next=head; } else if(head&&head->next&&n>1){ ListNode* temp=reverse(head->next,n-1,tail,begin); if(temp)temp->next=head; if(!temp)return NULL; } return head;
}
下面给出调用reverse的代码,首先应该获得第一段反转,如果反转的结果是NULL,说明整个链表的长度都不够,则直接返回原链表即可。否则的话,就找到新链表开始的位置,保存下来,作为最后返回时用。完成第一段反转后,下一段反转的起始应为第一段的末尾的下一个结点,然后继续reverse就ok了。
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode* keep=head;
int t=k;
while(t>1&&keep){
keep=keep->next;
t--;
}
ListNode* temp=reverse(head,k,head,NULL);
if(!temp)return head;
while(temp&&temp->next){
temp=reverse(temp->next,k,temp->next,temp);
}
return keep;
}