题目
题目来源:力扣(LeetCode)
给你一个链表,每 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]
思路分析
1、首先,我们创建一个虚拟头节点 hair,并将虚拟头节点指向链表的头节点。
2、然后,定义一个 pre 指针指向虚拟头节点,定义一个 tail 指针指向 pre 指针指向的节点
3、tail 指针每次向后移动一步,直到找到第 K 个节点,例如我们这里的 K 是 3,此时 tail 指针指向节点 3
4、此时我们找到了第一组 K 个节点的链表,我们先对这一组链表进行反转
5、定义一个 prev 指针 指向 tail 指针所指节点的下一个节点,定义一个 P 指针指向 head 节点,并定义一个        next 指针指向 P 指针所指向节点的下一个节点
6、将 P 指针所指向的节点的 next 指针域指向 prev 指针所指向的节点
7、将 prev 指针移动到 P 指针所指向的节点
8、将 P 指针移动到 next 指针所指向的节点上
9、然后将 next 指针继续往后移动,指向 P 指针所指向节点的下一个节点
10、继续将 prev 指针、P 指针、next 指针 往后移动,当 prev 指针与 tail 指针指向同一节点的时候,我们的 K 个一组链表翻转完了 
此时翻转完后的链表如下:
11、第一个 K 个一组的链表翻转完后,继续往后寻找下一组需要翻转的链表。将 pre 指针移动到 head 指针所指向的节点,让 pre 指针所指向的节点称为下一组待翻转链表的前驱节点,然后将 head 指针移动到 pre 指针所指向节点的下一个节点,让 head 指针所指向的节点称为下一组待翻转链表的头节点,同时把 tail 指针指向 pre 指针所指向的节点
12、然后 tail 节点继续往后移动 K 步,如果 tail 指针不为null,则继续翻转这一组链表,如果 tail 指针为 null,证明后面的节点已不足 K 个,返回链表,不再翻转后面的节点
const myReverse = (head, tail) => {let prev = tail.next;let p = head;while (prev !== tail) {const nex = p.next;p.next = prev;prev = p;p = nex;}return [tail, head];}var reverseKGroup = function(head, k) {// 创建一个虚拟头节点const hair = new ListNode(0);// 将 虚拟头节点指向链表的头节点hair.next = head;// 定义 pre 指针,指向头节点let pre = hair;while (head) {// 定义 tail 指针,指向 pre 指针所指向的节点let tail = pre;// 查看剩余部分长度是否大于等于 kfor (let i = 0; i < k; ++i) {tail = tail.next;if (!tail) {return hair.next;}}const nex = tail.next;[head, tail] = myReverse(head, tail);// 把子链表重新接回原链表pre.next = head;tail.next = nex;pre = tail;head = tail.next;}return hair.next;};
