package class04;
/***
* K个节点的组内逆序调整
*
* 实现k个节点的小组内部逆序,如果最后一组不够k个就保持原顺序。
* 例子:
* 调整前:1->2->3->4->5->6->7->8,k = 3
* 调整后:3->2->1->6->5->4->7->8
*/
// 测试链接:https://leetcode.com/problems/reverse-nodes-in-k-group/
public class Code04_ReverseNodesInKGroup {
//LeeCode在线测试时,不要提交这个类
public static class ListNode {
public int value;
public ListNode next;
}
public static ListNode reverseKGroup(ListNode head, int k) {
ListNode start = head;
ListNode end = getKGroupEnd(start, k);//end指向这一组的尾结点
if (end == null) {//如果end == null,那么说明第一组都没有凑齐。直接返回原来的头节点head。
return head;
}
//走到这一步,说明第一组凑齐了。
head = end;//head抓住end,end即第一组的尾结点。
//head打死也不撒手,就抓住end,不管你后边,别的节点怎么折腾,怎么翻转,最后就是要返回这个head。
reverse(start, end);//翻转组内链表
ListNode lastEnd = start;//定义lastEnd,即上一组的尾结点,指向这一组的开头,即start(如图d节点)。
while (lastEnd != null) {
start = lastEnd.next;//start跳到上一组尾结点的next,即这一组的头节点(如图d节点)。
end = getKGroupEnd(start, k);//组内翻转,end来到这一组的尾结点(如图f节点)。
if (end == null) {
return head;//1.什么时候会走这个return?在当前循环的小组中,小组的长度不够k个了,就提前走这个return。
}
reverse(start, end);//翻转组内链表
lastEnd.next = end;//上一组的尾结点的next,指向这一组的尾结点end(如图f节点)。
lastEnd = start;//lastEnd跳到这一组的头节点(如图d节点)。
//在每一次循环中,lastEnd的指向,一开始都是不对的,但是在循环的结尾会改对。
}
return head;//2.什么时候会走这个return?在链表长度正好是k的整数倍的时候。
}
/***
* 1.
* a -> b -> c -> d -> e -> f -> g -> hnull
* ^ ^
* | |
* head
* start end
*
*
* 2.head来到上一组的尾结点,即c的位置。最后要返回这个head。
*
* head
*
* a -> b -> c -> d -> e -> f -> g -> hnull
* ^ ^
* | |
* start end
*/
/***
* 组内翻转
* @param start 组内头节点
* @param end 组内尾结点
*/
public static void reverse(ListNode start, ListNode end) {
end = end.next;//end直接先往下跳一步
ListNode pre = null;
ListNode cur = start;
ListNode next = null;
while (cur != end) {
next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
start.next = end;
}
public static ListNode getKGroupEnd(ListNode start, int k) {
while (--k != 0 && start != null) {
start = start.next;
}
return start;
}
}