1、题目描述
给你链表的头节点 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]
提示:
- 链表中的节点数目为
n
1 <= k <= n <= 5000
0 <= Node.val <= 1000
进阶:你可以设计一个只用 O(1)
额外内存空间的算法解决此问题吗?
2、分析
要求:只用O(1)额外内存空间。
还是指针操作。外层只需要借助一个指针记录每批次处理完后cur应该出入的新位置即可。
内层在插入节点的时候也借助个临时指针,这没啥好说的。
(1)最外层是一个while循环for每批次的处理;
(2)对于完整的批次进行每批次的处理,处理流程如下:
1)首先我们要记录下每批次的头结点(被反转后它会作为结果的尾节点),我们需要在一批次结束后用其更新cur指针。
2)然后就是对批次内的k个元素进行反转,这里的反转其实就是将head指向的每个元素依次作为cur的next插入进去。
3)期间需要借助一个临时变量,协助完成构建新的连接关系。
(3)当不足一批次时,退出外层大循环追加到cur指针后面即可。
操作示意图如下。
注:其中phead表示每批次的头节点 batch_head。
3、实现代码
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <set>
#include <queue>
#include <map>
using namespace std;
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) {}
};
/* 1 2 3 4 5
大致思路: 要用指针存每个group的开头元素。 注: 或者上一个group的最后一个元素也行
对于完整够数的group逐次反转(由前往后);。
*/
class Solution{
public:
//判断后续节点是否够完整的一批次(看起来无法统一)
bool fullBatch(ListNode* head, int k){
while(head){
head = head->next;
k--; //2 1 0
}
if (k > 0){
return false;
}else{
return true;
}
}
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode dummy(0, nullptr);
ListNode* cur = &dummy;
ListNode* bhead; //记录当前这批的首元素(注:其会作为当前这批处理完后的尾元素,要用它来更新cur指针)
while(head){
int batch_size = k;
bool full = fullBatch(head, k);
if (!full) break;
bhead = head;
while(head!=nullptr && batch_size > 0){
ListNode* tmp = head;
head = head->next;
tmp->next = cur->next;
cur->next = tmp;
batch_size--;
}
cur = bhead;
}
cur->next = head;
return dummy.next;
}
void printList(ListNode* list){
while(list){
cout << list->val << ",";
list = list->next;
}
cout << endl;
}
};
int main()
{
Solution s1;
ListNode n15(5);
ListNode n14(4, &n15);
ListNode n13(3, &n14);
ListNode n12(2, &n13);
ListNode n11(1, &n12);
s1.printList(&n11);
int k = 3;
ListNode* res = s1.reverseKGroup(&n11, k);
s1.printList(res);
}