題目網址:https://leetcode.cn/problems/reorder-list/
題意:給一單向 linked list 的起始節點 head, 該 linked list 可表示為
L0 → L1 → … → Ln - 1 → Ln
將其重新排序為
L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …
不能只是單純改變節點內部的值, 必須進行實際的節點交換。


Solution:
想法:分成以下步驟
- 找到 linked list 的中點, 按照 141. Linked List Cycle 的方法
- 奇數時,
mid 指向中點
- 偶數時,
mid 指向右中點
- 因此, 最一開始要先讓
fast 先走一步, 這樣不管是奇偶數, mid 都會指向左中點
- 重要:截斷兩個 list ➔
mid->next = nullptr(容易忘記這步)
- reverse 右半部分
Ln → Ln - 1 → Ln - 2 → ...
- merge 左半和右半
class Solution { public: void reorderList(ListNode* head) { ListNode *mid = get_mid(head); ListNode *right = mid->next; mid->next = nullptr; right = reverse(right); merge(head, right); }
private: ListNode* get_mid(ListNode* head){ ListNode *slow = head, *fast = head->next; while (fast && fast->next) { slow = slow->next; fast = fast->next->next; } return slow; }
ListNode* reverse(ListNode* head){ ListNode *tail = head; ListNode *prev = nullptr, *nxt = nullptr; while (tail) { nxt = tail->next; tail->next = prev; prev = tail; tail = nxt; } return prev; }
void merge(ListNode* l1, ListNode* l2){ while (l1 && l2) { ListNode *n1 = l1->next; ListNode *n2 = l2->next;
l1->next = l2; l2->next = n1;
l1 = n1; l2 = n2; } } };
|
- time:$O(n)$ ➔ 遍歷整個 linked list
- space:$O(1)$ ➔ 只需常數空間