给你链表的头节点 head
,每 k
个节点一组进行翻转,请你返回修改后的链表。
k
是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k
的整数倍,那么请将最后剩余的节点保持原有顺序。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
示例 1:
输入:head = [1,2,3,4,5], k = 2 输出:[2,1,4,3,5]
示例 2:
输入:head = [1,2,3,4,5], k = 3 输出:[3,2,1,4,5]
迭代法解题思路:
创建一个头结点和两个指向头结点的指针pre和end,每次循环都让end相距pre K 个结点,创建start=pre->next, next=end->next。然后让end指向空,切断该子链表,然后把该子链表翻转后重新连接,继续下一循环,直到end->next为空。
// 无注释版
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:
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode* dummyHead=new ListNode(0);
dummyHead->next=head;
ListNode* pre=dummyHead;
ListNode* end=dummyHead;
while(end->next!=NULL){
for(int i=0;i
if(end==NULL)
break;
ListNode* start=pre->next;
ListNode* next=end->next;
end->next=NULL;
pre->next=reverse(start);
start->next=next;
pre=start;
end=pre;
}
return dummyHead->next;
}
private:
ListNode* reverse(ListNode* head)
{
ListNode* pre=NULL;
ListNode* curr=head;
while(curr!=NULL) {
ListNode* next=curr->next;
curr->next=pre;
pre=curr;
curr=next;
}
return pre;
}
};
// 注释版
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:
ListNode* reverseKGroup(ListNode* head, int k) {
// 创建头结点并连接上链表
ListNode* dummyHead=new ListNode(0);
dummyHead->next=head;
// 创建指针pre和end并指向头结点
ListNode* pre=dummyHead;
ListNode* end=dummyHead;
// 以k个结点为一组循环
while(end->next!=NULL){
// 每次都让end相距prek个距离
for(int i=0;i
// 如果end为空,结束循环
if(end==NULL)
break;
// 创建start和next指针
ListNode* start=pre->next;
ListNode* next=end->next;
// 切断该子链表
end->next=NULL;
// 让pre指向翻转后的子链表的第一结点
// reverse()实现子链表的翻转并返回第一结点
pre->next=reverse(start);
// 让翻转后的子链表的最后一结点
// 重新接上链表
start->next=next;
// 让pre和end指向翻转后的子链表的
// 最后一个结点
pre=start;
end=pre;
}
// 返回链表第一结点
return dummyHead->next;
}
private:
// 实现翻转子链表的函数
ListNode* reverse(ListNode* head)
{ // 传入子链表的第一结点赋给head
// 创建pre指向空和curr指向head
ListNode* pre=NULL;
ListNode* curr=head;
while(curr!=NULL) {
// 创建next指向curr的下一个结点
ListNode* next=curr->next;
// 让curr指向pre
curr->next=pre;
// 让pre指向curr,curr指向next
pre=curr;
curr=next;
} // 建议自己画图理解
// 返回翻转后子链表的第一结点
return pre;
}
};
递归法解题思路:
理解递归需要明确三要素:
1.调用递归返回的是什么
2.使用递归返回给谁(哪里使用递归)
3.递归的终止条件
1.改题使用递归应返回交换后的子链表的第一个结点
2.应把返回值(交换后的子链表的第一个结点)给上一级的子链表的第一结点(未翻转的第一结点,也就是翻转后的最后一个结点)的指针域
3.递归的终止条件是最后一个子链表的结点个数小于k。
// 无注释版
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:
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode* pre=head;
ListNode* end=head;
for(int i=1;i end=end->next; if(end==NULL) return head; ListNode* start=pre->next; pre->next=reverseKGroup(end->next,k); while(pre!=end) { ListNode* next=start->next; start->next=pre; pre=start; start=next; } return end; } }; // 注释版 struct ListNode { // 链表的定义 // 定义pre指向第一结点,end指向第k结点 // 终止条件:子链表结点个数小于k,不用翻转 // 所以返回子链表的第一结点 // 使用递归把下一级翻转后的子链表的第一 // 结点给上一级未翻转的子链表第一结点的指 //针域 // 实现翻转 // 递归的返回值(返回上一级) // 建议画图自己一步一步照着推。
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:
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode* pre=head;
ListNode* end=head;
for(int i=1;i
if(end==NULL)
return head;
ListNode* start=pre->next;
pre->next=reverseKGroup(end->next,k);
while(pre!=end) {
ListNode* next=start->next;
start->next=pre;
pre=start;
start=next;
}
return end;
}
};