【LetMeFly】143.重排链表:O(1)空间的做法 力扣题目链接:https://leetcode.cn/problems/reorder-list/
给定一个单链表 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
方法一:哈希表 / 数组 遍历链表,将链表节点存入哈希表中,映射关系为<[第几个节点, 节点]>
(其实这里使用数组也可以,虽然复杂度相同,但是数组的实际开销还是要小一些)
然后,用两个指针$l$和$r$,分别指向前面该处理的节点和后面该处理的节点
当前指针超过后指针时,退出循环。
注意事项:
用head遍历完链表后,head已经不再指向头节点,记得将head归位
记得将链表的最后一个节点的next置空
时间复杂度$O(n)$,其中$n$是链表节点个数
空间复杂度$O(n)$
AC代码 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 class Solution {public : void reorderList (ListNode* head) { unordered_map<int , ListNode*> ma; int cnt = 0 ; while (head) { ma[cnt++] = head; head = head->next; } head = ma[0 ]; int l = 1 , r = cnt - 1 ; bool front = false ; while (l <= r) { if (front) { head->next = ma[l++]; front = false ; } else { head->next = ma[r--]; front = true ; } head = head->next; } head->next = nullptr ; } };
使用数组:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution {public : void reorderList (ListNode* head) { vector<ListNode*> v; while (head) { v.push_back (head); head = head->next; } int l = 0 , r = v.size () - 1 ; head = v[0 ]; while (l <= r) { head->next = v[l++]; head = head->next; head->next = v[r--]; head = head->next; } head->next = nullptr ; } };
方法二:找中点 + reverse + 合并 一共分为三步:
找到链表的中点(使用快慢指针O(n) + O(1))
翻转后半链表(遍历O(n) + O(1))
链表合并(双指针O(n) + O(1))
注意事项:
在寻找链表中点的过程中,我们要返回的是中间节点的前一个节点
,因为“前半个链表的最后一个节点”的next要置空
奇数长度的数组[0, 1, 2]返回1,偶数长度的数组[0, 1]返回0
翻转后半部分列表的函数所接收参数的节点可能为空,需要特判
时间复杂度$O(n)$,其中$n$是链表节点个数
空间复杂度$O(1)$
AC代码 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 class Solution {private : ListNode* getMiddle (ListNode* head) { ListNode* fast = head, *slow = head; while (fast->next && fast->next->next) { slow = slow->next; fast = fast->next->next; } return slow; } ListNode* reverseList (ListNode* head) { if (!head) { return nullptr ; } ListNode* next = head->next; head->next = nullptr ; while (next) { ListNode* nextNext = next->next; next->next = head; head = next; next = nextNext; } return head; } void mergeList (ListNode* p1, ListNode* p2) { while (p1 && p2) { ListNode* p1next = p1->next; ListNode* p2next = p2->next; p1->next = p2, p2->next = p1next; p1 = p1next, p2 = p2next; } }public : void reorderList (ListNode* head) { ListNode* middle4pre = getMiddle (head); ListNode* middle = reverseList (middle4pre->next); middle4pre->next = nullptr ; mergeList (head, middle); } };
Python 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 class Solution : def getMiddle (self, head: ListNode ) -> ListNode: fast = slow = head while fast.next and fast.next .next : fast = fast.next .next slow = slow.next return slow def reverse (self, head: Optional [ListNode] ) -> Optional [ListNode]: if not head: return None next = head.next head.next = None while next : nextNext = next .next next .next = head head = next next = nextNext return head def merge (self, p1: ListNode, p2: Optional [ListNode] ): while p1 and p2: p1next = p1.next p2next = p2.next p1.next = p2 p2.next = p1next p1, p2 = p1next, p2next def reorderList (self, head: ListNode ) -> None : """ Do not return anything, modify head in-place instead. """ middle4pre = self .getMiddle(head) middle = self .reverse(middle4pre.next ) middle4pre.next = None self .merge(head, middle)
同步发文于CSDN,原创不易,转载请附上原文链接 哦~ Tisfy:https://letmefly.blog.csdn.net/article/details/126031446