題目描述:給定一個鏈結串列的頭節點 head 和整數 k,將鏈結串列每 k 個節點一組進行反轉,若最後剩餘的節點數不足 k 個,則保持原順序不變。不可更改節點的值,只能改變節點的指標。
解題思路:我們採用迭代搭配「虛擬頭節點(dummy node)」的方式,逐組反轉鏈結串列。
核心步驟:
dummy,方便統一處理邊界。groupPrev 指向每組反轉前的前驅節點。k 步,確認剩餘節點夠 k 個;若不夠,停止(保留原序)。k 個節點進行迭代反轉:利用 prev、curr 指標逐一翻轉指向。groupPrev 的 next 接上反轉後的頭節點,原頭節點(現為尾節點)接上下一組的起始。groupPrev 到當前組的尾節點,繼續下一輪。這樣整個過程是 O(n) 時間、O(1) 空間(不計遞迴版本的堆疊)。
時間複雜度:O(n) — 每個節點恰好被訪問常數次:一次探測(getKth)、一次反轉,總共 O(n)。
空間複雜度:O(1) — 迭代版本只使用固定數量的指標變數,不需要額外空間;若使用遞迴版本則為 O(n/k) 的遞迴堆疊深度。
1. Create a dummy node pointing to head; set groupPrev = dummy
2. Loop forever:
a. Call getKth(groupPrev, k) to find the k-th node from groupPrev
b. If no k-th node exists (fewer than k remaining), break
c. Set groupNext = kth->next (node after current group)
d. Reverse the k nodes between groupPrev and groupNext:
- Initialize prev = groupNext, curr = groupPrev->next
- While curr != groupNext: save tmp=curr->next, curr->next=prev, prev=curr, curr=tmp
e. Save tmp = groupPrev->next (original first node, now tail of reversed group)
f. Set groupPrev->next = kth (connect new head of reversed group)
g. Set groupPrev = tmp (advance to new tail for next iteration)
3. Return dummy.next方法一:遞迴法(Recursive Approach) 先遞迴處理第 k+1 個節點之後的串列,取得其反轉結果作為「後半部分的頭節點」,再反轉當前 k 個節點並拼接。程式碼更直觀,但遞迴深度為 O(n/k),當 k=1 時退化為 O(n) 堆疊,存在 stack overflow 風險。時間複雜度 O(n),空間複雜度 O(n/k)。
方法二:收集後整批反轉(Collect and Reverse) 使用一個暫存陣列收集每組的 k 個節點,整批反轉陣列後再重新連接。實作簡單,但需要 O(k) 額外空間存放每組節點,且每組都需要額外的記憶體分配,不符合 O(1) 空間要求。時間複雜度 O(n),空間複雜度 O(k)。