问题
https://leetcode-cn.com/problems/reorder-list/
给定一个单链表 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.
思路
首先观察重排以后的链表,会发现是头尾交替连接的
那么我们可以当作是两个链表的交叉合并
给定链表 1->2->3->4, 重新排列为 1->4->2->3
要合并的这两个链表其中一个是链表的前半部分,另一个是链表后半部分的反转
这样我们就把问题转化成几个子问题:找到链表的中间节点,对后半部分的链表进行反转、合并两个链表
时间复杂度:O(n)
空间复杂度:O(1)
程序
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reorderList(self, head: ListNode) -> None:
"""
Do not return anything, modify head in-place instead.
"""
dummy = ListNode(0)
dummy.next = head
# 找到中间节点
low = dummy
fast = dummy
while fast and fast.next:
low = low.next
fast = fast.next.next
mid = low.next
low.next = None
# 反转
mid = self.reverse(mid)
# 交叉合并两个链表
self.merge_two_list(dummy.next, mid)
# 反转链表
def reverse(self, head: ListNode) -> ListNode:
if not head:
return None
cur = None
while head:
node = head.next
head.next = cur
cur = head
head = node
return cur
# 交叉合并两个链表
def merge_two_list(self, l1: ListNode, l2: ListNode) -> ListNode:
dummy = ListNode(0)
cur = dummy
while l1 and l2:
# 先连 l1
cur.next = l1
cur = cur.next
l1 = l1.next
# 再连 l2
cur.next = l2
cur = cur.next
l2 = l2.next
# 对剩下的部分进行单独处理
if l1:
cur.next = l1
if l2:
cur.next = l2
return dummy.next