题目
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例 :
给定这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
说明 :
你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
思路
用的是精选题解的思路 因为有图 整个过程解释的非常详细。这道题比较难 在注释中我将每一步的作用都详细的写上了
源代码
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public ListNode reverseKGroup(ListNode head, int k) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode pre = dummy;
ListNode end = dummy;
while (end.next != null) {
for (int i = 0; i < k && end != null; i++) end = end.next;
if (end == null) break;
ListNode start = pre.next;
//提前保存下一次要反转的链表部分的第一个节点
ListNode next = end.next;
//分割本次反转与为即将将要进行反转的元素
end.next = null;
//reverse(start)返回的是本次反转后的最后一个节点
//pre初始为NULL pre.next = 本次反转最后一个节点位置 为下一次反转做准备 start = pre.next 因为上面有start = pre.next 所以现在start的位置为反转后部分的最后一个节点
pre.next = reverse(start);
//将反转后最后一个节点与还未反转部分的第一个节点相连接
start.next = next;
//为下一次反转设置前趋节点
pre = start;
//为下一次反转设置end节点 以便下一次反转通过end来确定下次反转的结束节点所在位置(那个for循环end = end.next)
end = pre;
}
return dummy.next;
}
private ListNode reverse(ListNode head) {
ListNode pre = null;
ListNode curr = head;
while (curr != null) {
ListNode next = curr.next;
curr.next = pre;
pre = curr;
curr = next;
}
return pre;
}