题目要求
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例 :
给定这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
说明 :
你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
题解
https://github.com/soulmachine/leetcode
递归版
链表的题,多说无益,画图吧。
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
if(head==nullptr||head->next==nullptr||k<2)
return head;
ListNode *next_group=head;
for(int i=0;i<k;++i){
if(next_group)
next_group=next_group->next;
else
return head;
}
// next_group is the head of next group
// new_next_group is the new head of next group after reversion
ListNode *new_next_group=reverseKGroup(next_group,k);
ListNode *prev=nullptr,*cur=head;
while(cur!=next_group){
ListNode *next=cur->next;
//除了第一次,即原来每组最小的数需要指向翻转好的下一组的头之外,都应该指向原来在其之前的元素
cur->next=prev?prev:new_next_group;
prev=cur;
cur=next;
}
return prev; // prev will be the new head of this group
}
};
迭代版
class Solution {
public:
// prev 是 first 前一个元素, [begin, end] 闭区间,保证三者都不为 null
// 返回反转后的倒数第 1 个元素(下一组第一个元素之前的位置)
ListNode* reverse(ListNode *prev,ListNode *begin,ListNode *end){
ListNode *end_next=end->next;
for(ListNode *p=begin,*cur=p->next,*next=cur->next;
cur!=end_next;
p=cur,cur=next,next=next?next->next:nullptr){
cur->next=p;
}
begin->next=end_next;
prev->next=end;
return begin;
}
ListNode* reverseKGroup(ListNode* head, int k) {
if(head==nullptr||head->next==nullptr||k<2)
return head;
ListNode dummy(-1);
dummy.next = head;
for(ListNode *prev=&dummy,*end=head;end;end=prev->next){
for(int i=1;i<k&&end;i++)
end=end->next;
if(end==nullptr) break; // 不足 k 个
prev=reverse(prev,prev->next,end);
}
return dummy.next;
}
};