题目描述
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
分析
这个题的思路很简单,就是模拟。翻转链表我们都知道,这个题加了一个条件,K个一组。
这就带来了一些额外需要考虑的问题:
怎么限制只翻转K个?
- 可以计数(s<k),也可以使用指针判断(t!=tail)。
K个一组翻转完毕后,怎么和前后的部分连接起来?
- 翻转之前这K个的头指针就是翻转之后的尾指针。
- 翻转之前的上一段的尾要和翻转之后的下一段的头连接。
- 对于头指针可以特判,可以加虚拟头指针
代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
//翻转的头指针head,第K+1个节点是K1_node 也就是翻转之后尾指针要指向K+1个节点。
ListNode* reverse(ListNode* K1_node,ListNode* head,int K){
ListNode* a=K1_node;
ListNode* b=head;
//cout<<"test "<<b->val<<endl;
int s=0;
while (s<K){
ListNode* c=b->next;
b->next=a;
a=b;
b=c;
s++;
}
//cout<<"test "<<a->val<<endl;
return a;
}
ListNode* reverseKGroup(ListNode* head, int K) {
ListNode* new_head=NULL; //新的头指针
ListNode* a=head; //翻转之前的头
ListNode* tail=NULL; //翻转之后的尾
ListNode* t=head; //用于遍历每组的第K+1个
bool b=0; //用来判断总数是否小于K个
while (1){
int s=0;
while (t!=NULL){ //数出K个
t=t->next;
s++;
if (s==K) break;
}
if (s!=K) break; //说明不够K个,就不需要翻转了。
if (new_head==NULL){
new_head=reverse(t,a,K); //第一次翻转的头是新链表的头
b=1;
} else {
ListNode * p=reverse(t,a,K); //之后的头需要和之前的连接
tail->next=p; //连接上一段的尾和下一段的头
}
tail=a; //之前的头 翻转之后成为 尾
a=t; //下一段的翻转之前的头是t
}
if (b==0) new_head=head;
return new_head;
}
};