25. K 个一组翻转链表 - 力扣(LeetCode)

给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。

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:
ListNode* reverseList(ListNode* head) {
ListNode* prev = nullptr;
ListNode* curr = head;
while (curr) {
ListNode* next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
return prev;
}

ListNode* findth(ListNode* head,int k) {//找到head的第k个结点
ListNode* dummy=new ListNode(0,head);
ListNode* cur = dummy;
while (k--) {
if(cur){
cur=cur->next;
}else{
return head;//如果没有k个节点,返回链表的头结点
}
}
delete dummy;
return cur;
}

ListNode* reverseKGroup(ListNode* head, int k) {
if(k==1)return head;
ListNode* cur = head;
ListNode* kTh=nullptr;
ListNode* kThNext=nullptr;
ListNode* finded=nullptr;
ListNode* reversed=nullptr;
ListNode* Firstreversed=nullptr;//记录新的链表头结点

while(cur){

kTh=findth(cur,k);//找到翻转前当前结点起的第k个结点
// cout<<"-----翻转前--------"<<endl;

if(kTh == cur||kTh==nullptr){//剩余未翻转的结点不足k个或者全部翻转完成
finded->next=cur;
break;
}else{
// cout<<kTh->val<<endl;
kThNext=kTh->next;
kTh->next=nullptr;

reversed=reverseList(cur);
//判断起始情况,连接反转后的链表
if(finded)finded->next=reversed;
else Firstreversed=reversed;

finded=findth(reversed,k);//找到翻转后当前结点起的第k个结点

// cout<<"-----翻转hou--------"<<endl;
// cout<<finded->val<<endl;
cur=kThNext;

}
}
return Firstreversed;
}
};

考虑递归解法

public ListNode reverseKGroup(ListNode head, int k) {
if(head == null) return null;
ListNode pre = head, index = head.next;//双指针操纵反转
int m = 0;
//翻转操作
while (++m < k && index != null) {
pre.next = index.next;
index.next = head;
head = index;
index = pre.next;
}
if(m < k) {
//不足k个元素,反转回去
return reverseKGroup(head, m);
}
pre.next = reverseKGroup(index, k);//index位置翻转下一个窗口
return head;
}