6.重排連結串列
阿新 • • 發佈:2021-12-16
題目描述
給定一個連結串列 L:L0→L1→…→Ln−1→LnL:L0→L1→…→Ln−1→Ln,將它變成 L0→Ln→L1→Ln−1→L2→Ln−2→…L0→Ln→L1→Ln−1→L2→Ln−2→…
你不能改變節點的值,只能改變節點的指標。
樣例
輸入:head = [1,2,3,4]
輸出:[1,4,2,3]
輸入:head = [1,2,3,4,5]
輸出:[1,5,2,4,3]
時間複雜度O(n)
一共需要掃描連結串列3次,一次求總長度,一次將後半段的連結串列反向,一次將兩段連結串列交替插入前半段,所以時間複雜度為O(n)
說明
- 將後半段的指標都反向
- 用兩個指標分別從1和n開始往中間掃描
- 結束條件: left != right
程式碼
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */ class Solution { public: void reorderList(ListNode* head) { // 先求出連結串列的長度 ListNode* link = head; int sum = 0; while (link) { link = link->next; sum++; } if (sum <= 2) { return; } // 找到最後一個結點 ListNode* r = head; int num = sum - 1; while (num--) { r = r->next; } int median = sum / 2; // 找到中間節點 ListNode* mid = head; while (median--) { mid = mid->next; } ListNode* a = mid; ListNode* b = mid->next; while (b) { ListNode* c = b->next; b->next = a; a = b; b = c; } mid->next = nullptr; // 定義左邊和右邊的遍歷結點 ListNode* left = head; ListNode* right = r; // 定義總結點 ListNode* all = new ListNode(0); while (left != right) { all->next = left; all = all->next; left = left->next; all->next = right; all = all->next; if (right->next) { right = right->next; } } } };