题目描述
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
来源:力扣(LeetCode)题目链接
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
/**
* 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) {}
* };
*/
题解1(栈)
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode* dummy = new ListNode;
ListNode* temp = new ListNode;
temp = dummy;
stack<ListNode*> stacks;
while(head){
for(int i = 0; i < k; i++){
if(! head) return dummy->next;
stacks.push(head);
head = head->next;
}
while(!stacks.empty()){
temp->next = stacks.top();
stacks.pop();
temp = temp->next;
}
//防止不足k个
temp->next = head;
}
return dummy->next;
}
};
// 更直接的想法
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
if(!head || !head->next)
return head;
// 头节点
ListNode* dnode = new ListNode(0, nullptr);
ListNode* p = dnode;
stack<ListNode*> stk;
while(head){
stk.push(head);
head = head->next;
if(k == stk.size()){
while(!stk.empty()){
p->next = stk.top();
p = p->next;
stk.pop();
}
// 考虑到可能不足k的情况,每次都先指向此刻的head(下一个k段的首个节点)
p->next = head;
}
}
return dnode->next;
}
};
题解2(递归)
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
//常数优化
if(! head || k < 2) return head;
int c = 1;
ListNode* cc = head;
while(c < k && cc){
c++;
cc = cc->next;
}
if(! cc) return head;
ListNode* dummy = cc->next;
//下一组
ListNode* prev = reverseKGroup(dummy, k);
ListNode* cur, *nex;
cur = head;
//逆序拆解过程
//1->2->3->4 k = 3
//1->4 --> 2->1 --> 3->2
while(cur != dummy){
nex = cur->next;
cur->next = prev;
prev = cur;
cur = nex;
}
return cc;
}
};
// 精讲版
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
if(!head || !head->next)
return head;
ListNode* tmp = head;
for(int i=0; i < k; i++){
if(tmp)
tmp = tmp->next;
else return head;
}
// !!每一次的"head"都是在函数头接收的指针往后挪了k位的位置!!
// 如果剩余不足k个,则返回的是未移动的head
// 此处递归含义很好懂:这个op是每k个做一次,很容易联想到递归(对某些数据重复操作),为了节省时间只做优化类迭代
ListNode* p = reverseKGroup(tmp, k);
// p 实际上是下一个k段的起始(可能是不足k个段的head,也可能是nullptr)
// 递归退出后的循环处理的都是此时的p前k位的逆序
// 思考时只考虑一级递归做什么
for(int i=0; i < k; i++){
// tmp 意义同p:两个尾节点
tmp = head->next;
// 逆序操作:链表指向换方向
//思考一下:原来的首节点要指向下一个k段的首节点,剩下的节点指向逆向:1->2->3为例, 1->4后,只需要迭代:1.next(2) ->1, 2.next(3)->2,最后达到3->2->1->4
head->next = p;
p = head;
// 迭代
head = tmp;
}
// 每个k段的首节点
return p;
}
};
在这里插入图片描述