给定一个单链表 L
__ 的头节点 head
,单链表 L
表示为:
L0 -> L1 -> … -> Ln-1 -> Ln
请将其重新排列后变为:
L0 -> Ln -> L1 -> Ln-1 -> L2 -> Ln-2 -> …
不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例 1:
**输入:** head = [1,2,3,4]
**输出:** [1,4,2,3]
示例 2:
**输入:** head = [1,2,3,4,5]
**输出:** [1,5,2,4,3]
提示:
链表的长度范围为 [1, 5 * 104]
1 <= node.val <= 1000
注意:本题与主站 143 题相同:https://leetcode-cn.com/problems/reorder-list/
方法一:线性表 因为链表不支持下标访问,所以我们无法随机访问链表中任意位置的元素。
因此比较容易想到的一个方法是,我们利用线性表存储该链表,然后利用线性表可以下标访问的特点,直接按顺序访问指定元素,重建该链表即可。
代码
[sol1-C++] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Solution {public : void reorderList (ListNode *head) { if (head == nullptr ) { return ; } vector<ListNode *> vec; ListNode *node = head; while (node != nullptr ) { vec.emplace_back (node); node = node->next; } int i = 0 , j = vec.size () - 1 ; while (i < j) { vec[i]->next = vec[j]; i++; if (i == j) { break ; } vec[j]->next = vec[i]; j--; } vec[i]->next = nullptr ; } };
[sol1-Java] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Solution { public void reorderList (ListNode head) { if (head == null ) { return ; } List<ListNode> list = new ArrayList <ListNode>(); ListNode node = head; while (node != null ) { list.add(node); node = node.next; } int i = 0 , j = list.size() - 1 ; while (i < j) { list.get(i).next = list.get(j); i++; if (i == j) { break ; } list.get(j).next = list.get(i); j--; } list.get(i).next = null ; } }
[sol1-Golang] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 func reorderList (head *ListNode) { if head == nil { return } nodes := []*ListNode{} for node := head; node != nil ; node = node.Next { nodes = append (nodes, node) } i, j := 0 , len (nodes)-1 for i < j { nodes[i].Next = nodes[j] i++ if i == j { break } nodes[j].Next = nodes[i] j-- } nodes[i].Next = nil }
[sol1-C] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 void reorderList (struct ListNode* head) { if (head == NULL ) { return ; } struct ListNode * vec [40001]; struct ListNode * node = head; int n = 0 ; while (node != NULL ) { vec[n++] = node; node = node->next; } int i = 0 , j = n - 1 ; while (i < j) { vec[i]->next = vec[j]; i++; if (i == j) { break ; } vec[j]->next = vec[i]; j--; } vec[i]->next = NULL ; }
[sol1-Python3] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution : def reorderList (self, head: ListNode ) -> None : if not head: return vec = list () node = head while node: vec.append(node) node = node.next i, j = 0 , len (vec) - 1 while i < j: vec[i].next = vec[j] i += 1 if i == j: break vec[j].next = vec[i] j -= 1 vec[i].next = None
复杂度分析
方法二:寻找链表中点 + 链表逆序 + 合并链表 注意到目标链表即为将原链表的左半端和反转后的右半端合并后的结果。
这样我们的任务即可划分为三步:
找到原链表的中点(参考「876. 链表的中间结点 」)。
我们可以使用快慢指针来 O(N) 地找到链表的中间节点。
将原链表的右半端反转(参考「206. 反转链表 」)。
将原链表的两端合并。
代码
[sol2-C++] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 class Solution {public : void reorderList (ListNode* head) { if (head == nullptr ) { return ; } ListNode* mid = middleNode (head); ListNode* l1 = head; ListNode* l2 = mid->next; mid->next = nullptr ; l2 = reverseList (l2); mergeList (l1, l2); } ListNode* middleNode (ListNode* head) { ListNode* slow = head; ListNode* fast = head; while (fast->next != nullptr && fast->next->next != nullptr ) { slow = slow->next; fast = fast->next->next; } return slow; } ListNode* reverseList (ListNode* head) { ListNode* prev = nullptr ; ListNode* curr = head; while (curr != nullptr ) { ListNode* nextTemp = curr->next; curr->next = prev; prev = curr; curr = nextTemp; } return prev; } void mergeList (ListNode* l1, ListNode* l2) { ListNode* l1_tmp; ListNode* l2_tmp; while (l1 != nullptr && l2 != nullptr ) { l1_tmp = l1->next; l2_tmp = l2->next; l1->next = l2; l1 = l1_tmp; l2->next = l1; l2 = l2_tmp; } } };
[sol2-Java] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 class Solution { public void reorderList (ListNode head) { if (head == null ) { return ; } ListNode mid = middleNode(head); ListNode l1 = head; ListNode l2 = mid.next; mid.next = null ; l2 = reverseList(l2); mergeList(l1, l2); } public ListNode middleNode (ListNode head) { ListNode slow = head; ListNode fast = head; while (fast.next != null && fast.next.next != null ) { slow = slow.next; fast = fast.next.next; } return slow; } public ListNode reverseList (ListNode head) { ListNode prev = null ; ListNode curr = head; while (curr != null ) { ListNode nextTemp = curr.next; curr.next = prev; prev = curr; curr = nextTemp; } return prev; } public void mergeList (ListNode l1, ListNode l2) { ListNode l1_tmp; ListNode l2_tmp; while (l1 != null && l2 != null ) { l1_tmp = l1.next; l2_tmp = l2.next; l1.next = l2; l1 = l1_tmp; l2.next = l1; l2 = l2_tmp; } } }
[sol2-Golang] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 func middleNode (head *ListNode) *ListNode { slow, fast := head, head for fast.Next != nil && fast.Next.Next != nil { slow = slow.Next fast = fast.Next.Next } return slow } func reverseList (head *ListNode) *ListNode { var prev, cur *ListNode = nil , head for cur != nil { nextTmp := cur.Next cur.Next = prev prev = cur cur = nextTmp } return prev } func mergeList (l1, l2 *ListNode) { var l1Tmp, l2Tmp *ListNode for l1 != nil && l2 != nil { l1Tmp = l1.Next l2Tmp = l2.Next l1.Next = l2 l1 = l1Tmp l2.Next = l1 l2 = l2Tmp } } func reorderList (head *ListNode) { if head == nil { return } mid := middleNode(head) l1 := head l2 := mid.Next mid.Next = nil l2 = reverseList(l2) mergeList(l1, l2) }
[sol2-C] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 struct ListNode* middleNode (struct ListNode* head) { struct ListNode * slow = head; struct ListNode * fast = head; while (fast->next != NULL && fast->next->next != NULL ) { slow = slow->next; fast = fast->next->next; } return slow; } struct ListNode* reverseList (struct ListNode* head) { struct ListNode * prev = NULL ; struct ListNode * curr = head; while (curr != NULL ) { struct ListNode * nextTemp = curr->next; curr->next = prev; prev = curr; curr = nextTemp; } return prev; } void mergeList (struct ListNode* l1, struct ListNode* l2) { struct ListNode * l1_tmp ; struct ListNode * l2_tmp ; while (l1 != NULL && l2 != NULL ) { l1_tmp = l1->next; l2_tmp = l2->next; l1->next = l2; l1 = l1_tmp; l2->next = l1; l2 = l2_tmp; } } void reorderList (struct ListNode* head) { if (head == NULL ) { return ; } struct ListNode * mid = middleNode(head); struct ListNode * l1 = head; struct ListNode * l2 = mid->next; mid->next = NULL ; l2 = reverseList(l2); mergeList(l1, l2); }
[sol2-Python3] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 class Solution : def reorderList (self, head: ListNode ) -> None : if not head: return mid = self.middleNode(head) l1 = head l2 = mid.next mid.next = None l2 = self.reverseList(l2) self.mergeList(l1, l2) def middleNode (self, head: ListNode ) -> ListNode: slow = fast = head while fast.next and fast.next .next : slow = slow.next fast = fast.next .next return slow def reverseList (self, head: ListNode ) -> ListNode: prev = None curr = head while curr: nextTemp = curr.next curr.next = prev prev = curr curr = nextTemp return prev def mergeList (self, l1: ListNode, l2: ListNode ): while l1 and l2: l1_tmp = l1.next l2_tmp = l2.next l1.next = l2 l1 = l1_tmp l2.next = l1 l2 = l2_tmp
复杂度分析