Bootstrap

C++——K个一组翻转链表leetcode25

K个一组翻转链表leetcode25

题目描述

给你链表的头节点 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;
}
;