題目
給你一個鏈表,每 k 個節點一組進行翻轉,請你返回翻轉后的鏈表。
k 是一個正整數,它的值小于或等于鏈表的長度。
如果節點總數不是 k 的整數倍,那么請將最后剩余的節點保持原有順序。
示例 :
給定這個鏈表:1->2->3->4->5
當 k = 2 時,應當返回: 2->1->4->3->5
當 k = 3 時,應當返回: 3->2->1->4->5
說明 :
你的算法只能使用常數的額外空間。
你不能只是單純的改變節點內部的值,而是需要實際的進行節點交換。
思路
用的是精選題解的思路 因為有圖 整個過程解釋的非常詳細。這道題比較難 在注釋中我將每一步的作用都詳細的寫上了
image
image
源代碼
/**
* 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;
}