难度中等428收藏分享切换为英文接收动态反馈
给定一个单链表 L:L0→L1→…→Ln-1→Ln , 将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→…
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例 1:
给定链表 1->2->3->4, 重新排列为 1->4->2->3.示例 2:
给定链表 1->2->3->4->5, 重新排列为 1->5->2->4->3.因为链表不支持下标访问,所以我们无法随机访问链表中任意位置的元素。
因此比较容易想到的一个方法是,我们利用线性表存储该链表,然后利用线性表可以下标访问的特点,直接按顺序访问指定元素,重建该链表即可。
复杂度分析
时间复杂度:O(N),其中 N 是链表中的节点数。
空间复杂度:O(N),其中 N 是链表中的节点数。主要为线性表的开销。
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. 反转链表」)。
我们可以使用迭代法实现链表的反转。 将原链表的两端合并。
因为两链表长度相差不超过 1,因此直接合并即可
复杂度分析
时间复杂度:O(N),其中 N 是链表中的节点数。
空间复杂度:O(1)。
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作者:LeetCode-Solution 链接:https://leetcode-cn.com/problems/reorder-list/solution/zhong-pai-lian-biao-by-leetcode-solution/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。