题目描述
给你链表的头节点 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]
思路
考虑先找出整个链表的长度,然后判读有几组需要翻转的子链表。对于第一组子链表需要特殊处理,因为第一组子链表不需要把上一组的末尾赋给其开头,并且第一组的子链表翻转之后需要把新的链表头部保存下来。对于后面的子链表,每次翻转完之后,将上一组的末尾的next指向这一组的开头的节点,并更新末尾节点指针。最后在全部完成后,将最后一组的末尾节点的指针指向下一组的开头。
#include <iostream>
using namespace std;
typedef struct ListNode
{
int val;
ListNode* next;
ListNode():val(0), next(nullptr){}
ListNode(int v):val(v), next(nullptr){}
ListNode(int v, ListNode* n):val(v), next(n){}
} ListNode;
ListNode* solution(ListNode* head, int k)
{
int len = 0;
for(ListNode* cur = head; cur!=nullptr; cur = cur->next)
len++;
int nums = len/k; // 一共需要几组
ListNode* cur = head; // 当前节点
ListNode* newHead = nullptr;
int not_first = 0;// 指示是否为第一个节点
ListNode* tail = head;
for(int i = 0; i<nums; i++)
{
ListNode* dummy_head = new ListNode(0, cur); // 子链表的伪头节点
ListNode* preNode = dummy_head;
ListNode* nextNode = cur->next;
for(int j = 0; j<k; j++)
{
cur->next = preNode;
preNode = cur;
cur = nextNode;
if(nextNode)
nextNode = nextNode->next;
}
if(!newHead ) // 用于保存最终的头节点
newHead = preNode;
if(not_first) // 如果不是第一组子链表,就把上一组的末尾连到这一组的开头
{
tail->next = preNode;
for(int s = 0; s<k; s++)
tail = tail->next; // 更新tail
}
not_first++;
delete dummy_head;
}
tail->next = cur;
return newHead;
}