題目
給你一個鏈表,每 k 個節點一組進行翻轉,請你返回翻轉後的鏈表。
k 是一個正整數,它的值小於或等於鏈表的長度。
如果節點總數不是 k 的整數倍,那麼請將最後剩餘的節點保持原有順序。
示例:
給你這個鏈表:1->2->3->4->5
當 k = 2 時,應當返回: 2->1->4->3->5
當 k = 3 時,應當返回: 3->2->1->4->5
說明:
你的算法只能使用常數的額外空間。 你不能只是單純的改變節點內部的值,而是需要實際進行節點交換。
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/reverse-nodes-in-k-group
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
分析
這道題目標記的難度是困難,但是我感覺是一道容易題。今天是第四天學習Java,於是我用我那三腳貓的Java進行了實現。
說一下思路,
步驟分解:
- 鏈表分區爲已翻轉部分+待翻轉部分+未翻轉部分
- 每次翻轉前,要確定翻轉鏈表的範圍,這個必須通過 k 此循環來確定
- 需記錄翻轉鏈表前驅和後繼,方便翻轉完成後把已翻轉部分和未翻轉部分連接起來
- 初始需要兩個變量 pre 和 end,pre 代表待翻轉鏈表的前驅,end 代表待翻轉鏈表的末尾
- 經過k此循環,end 到達末尾,記錄待翻轉鏈表的後繼 next = end.next
- 翻轉鏈表,然後將三部分鏈表連接起來,然後重置 pre 和 end 指針,然後進入下一次循環
- 特殊情況,當翻轉部分長度不足 k 時,在定位 end 完成後,end==null,已經到達末尾,說明題目已完成,直接返回即可
時間複雜度爲 O(n*K)O(n∗K) 最好的情況爲 O(n)O(n) 最差的情況未 O(n^2)O(n ^2 )
空間複雜度爲 O(1)O(1) 除了幾個必須的節點指針外,我們並沒有佔用其他空間
代碼
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
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;
pre.next = reverse(start);
start.next = next;
pre = start;
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;
}
}
運行結果
效率是OK了,但是空間有些莫名其妙。
從官方題解複製了以下,內存排名並不能更好看。
感謝大家的點贊和評論。