一、题目
题目描述
将给出的链表中的节点每\ k k 个一组翻转,返回翻转后的链表
如果链表中的节点数不是\ k k 的倍数,将最后剩下的节点保持原样
你不能更改节点中的值,只能更改节点本身。
要求空间复杂度 \ O(1) O(1)
例如:
给定的链表是1\to2\to3\to4\to51→2→3→4→5
对于 \ k = 2 k=2, 你应该返回 2\to 1\to 4\to 3\to 52→1→4→3→5
对于 \ k = 3 k=3, 你应该返回 3\to2 \to1 \to 4\to 53→2→1→4→5
示例1
输入
{1,2,3,4,5},2
返回值
{2,1,4,3,5}
二、思路
1、首先要知道反转整个链表的方法
定义三个指针,详情见我之前发过的一篇反转链表的博客,https://blog.csdn.net/weixin_45794299/article/details/115786312?spm=1001.2014.3001.5502
2、 在此基础上,每k个反转,切开,最后再连起来
第一步:考虑链表为空或者只有一个节点的情况,返回nullptr;
第二步:统计链表的总节点数
第三步:计算多少组,以及定义两个数组,Lpre数组用来存储反转后每一组的最后一个;Last数组用来存储反转后每一组的第一个,但是当节点数不是k的整数倍的时候,Last数组需要多加一个,因为它存储的第一个是反转后的首元结点
第四步:在for循环里,每一组都反转,反转完一组后,用两个数组记录每一组的第一个指针和最后一个指针,并把三个指针中的pre指针置为空,使各个分组暂时失去联系
第五步:反转是否整除,如果不整除则,Last数组添加刚好不整除的剩余部分的第一个节点;如果整除,则Last数组最后一个添加为nullptr;
第六步:把Lpre数组和Last数组连接起来
第七步:返回Last数组的第一个,及首元结点
三、代码
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
class Solution {
public:
/**
*
* @param head ListNode类
* @param k int整型
* @return ListNode类
*/
ListNode* reverseKGroup(ListNode* head, int k) {
if(head ==nullptr || head->next==nullptr)
{
return head;
}
ListNode *node=head;
int Count=0;
while(node!=nullptr)
{
node=node->next;
Count++;
}
//计算多少组
int Time=Count/k;
int Rel=Count%k;
ListNode *Lpre[Time];
ListNode *Last[Time+1];
//定义三个指针用于反转
ListNode *pre=nullptr;
ListNode *cur=head;
ListNode *nxt;
//定义两个指针记录
ListNode *lpre,*last;
//开始处理
for(int i=0;i<Time;++i)
{
//记录第一个指针
Lpre[i]=cur;
for(int j=0;j<k;++j)
{
//反转
nxt=cur->next;
cur->next=pre;
pre=cur;
cur=nxt;
}
//反转完一组后
//记录最后一个指针
Last[i]=pre;
//pre重新置为空
pre=nullptr;
}
if(Rel!=0)
{
//长度不是K的倍数
Last[Time]=cur;
}
else
{
//如果长度刚好是k的倍数
Last[Time]=nullptr;
}
//将各段连接起来
for(int i=0;i<Time;++i)
{
Lpre[i]->next=Last[i+1];
}
//返回首节点
return Last[0];
}
};