给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。
k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
本题可以看作92. 反转链表 II的一个进阶题,反转多个给定长度的链表段。反转核心还是最基础的前后节点进行后移,如下:
while(cur != null){// 只要当前不为空 可以一致循环处理
// 获取当前指针的下一节点
ListNode next = cur.next;
// 当前指针之前的下一个为 next ,现在反向指向前一个 pre
cur.next = pre;
// 向后移动继续下一个节点处理,例如开始是null,1 那么这是就变成 1,2开始反转指针
pre = cur;
cur = next;
}
本题相对于92. 反转链表 II 多了反转多少个链表段,在解题时使用变量count为链表长度,然后每反转一个链表段count就减去K直到count小于K。每次反转一段时(K个节点)我们就使用前后节点指针反向,最终得到反转段右节点的下一节点(cur)和反转段的头节点(pre),然后将每个反转段进行关联。
代码如下:
public ListNode reverseKGroup(ListNode head, int k) {
int count = 0;
ListNode countHead = head;
while (countHead != null) {
countHead = countHead.next;
count++;
}
// 哨兵节点 及 每段前节点初始化
ListNode dummy = new ListNode(0, head), segmentPre = dummy;
//当前节点、 前一节点(此处为null,反转后的每段结果为pre) 初始化
ListNode cur = head, pre = null;
// ============= 只有当整除K时进行反转 start =============
while (count >= k) {
// ============= 每段进行指针反向操作 start =============
int segmentK = k;
while (segmentK > 0) {
// 缓存下一节点便于后移
ListNode next = cur.next;
// 当前节点指针反向 指向前一节点
cur.next = pre;
// 前一节点后移
pre = cur;
// 当前节点后移
cur = next;
// 当前片段个数减一
segmentK--;
}
// ============= 每段进行指针反向操作 end =============
// ============= 每段进行指针反向操作 返回的结果为pre
// ============= 每段进行首尾指向 start =============
// 缓存下一节点便于后移 segmentPre.next = pre,segmentPre.next.next = cur
// 相当于 segmentPre 只用了第二个节点(第一个为0即为哨兵节点),将上述反转段插入到第二个节点上(相对于某段而言,毕竟segmentPre会随之后移)
ListNode next = segmentPre.next;
// 设置每段下一次循环的当前节点 其实当前为 segmentPre.next
segmentPre.next.next = cur;
// 将上述反转的
segmentPre.next = pre;
// segmentPre后移
segmentPre = next;
// 数值一次减少K
count -= k;
// ============= 每段进行首尾指向 end =============
}
// ============= 只有当整除K时进行反转 end =============
return dummy.next;
}
运行结果如下:
(含有注释效果会低,去掉注释后内存由提升)
个人见解不喜勿喷!!!