25. K 个一组翻转链表
题目:给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例:
给你这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
说明:
你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
//第二种
//递归
class Solution {
public:
//反转链表----这里两个递归会栈溢出
ListNode* _reverse(ListNode* head,ListNode* end)
{
ListNode* cur = head;
while(cur->next != end)
{
ListNode* temp = cur->next;
cur->next = temp->next;
temp->next = head;
head = temp;
}
return head;
}
//递归
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode* cur = head;
for(int i = 0 ; i < k ; ++i)
{
if(!cur){return head;}
cur = cur->next;
}
ListNode* new_head = _reverse(head,cur);
head->next = reverseKGroup(cur,k); //这时的head就是尾部结点了
return new_head;
}
};
----------------------------------------------------
//第一种
/*
1.确定pre->next至end的区间
2.进行部分反转
心得:部分反转的思路与递归时所写的思路相似
*/
class Solution {
public:
//反转链表(递归法)
ListNode* _reverse(ListNode* head,ListNode* end)
{
if(head == end) return head;
ListNode* rhead = _reverse(head->next,end);
ListNode* rtail = head->next;
rtail->next = head;
return rhead;
}
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode* dummy = new ListNode(-1);
dummy->next = head;
ListNode* pre = dummy;
while(pre && pre->next)
{
ListNode* end = pre;
//确定end
int i;
for(i = 0 ; i < k && end->next != nullptr ; i++) end = end->next;
//如果后面不足k个结点,说明后面就不用进行反转操作
if(i != k) break;
//部分反转
ListNode* next = end->next;
ListNode* rhead = _reverse(pre->next,end);
ListNode* rtail = pre->next;
pre->next = rhead;
rtail->next = next;
pre = rtail;
}
ListNode* ret = dummy->next;
delete dummy;
return ret;
}
};