题目
给定一个单链表 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 ) o(n) o(n)版:用1个双端队列保存链表,然后每次从头pop一个,从尾pop一个,依次连接
看了题解,有个空间复杂度 o ( 1 ) o(1) o(1)版的解法。先用快慢指针找出链表的中点,然后反转后半段链表,再把前半段和后半段链表合并成1个即可。
注意用快慢指针找到中点后,不管是奇数个节点还是偶数个节点,要反转的都是slow
指向的后一个节点开始的链表。
代码
# 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.
"""
ret_head = ListNode(-1)
dequeue = collections.deque([])
p = head
while p:
dequeue.append(p)
p = p.next
p = ret_head
pop_from_head = True
while dequeue:
if pop_from_head:
next_node = dequeue.popleft()
pop_from_head = False
else:
next_node = dequeue.pop()
pop_from_head = True
p.next = next_node
p = p.next
p.next = None
return ret_head.next
原地版:
# 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: Optional[ListNode]) -> None:
"""
Do not return anything, modify head in-place instead.
"""
def reverse(head: ListNode) -> ListNode:
prev, p = None, head
while p:
pn = p.next
p.next = prev
prev, p = p, pn
return prev
ret_head = ListNode(-1)
ret_head.next = head
# find middle node
slow, fast = ret_head, head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if fast:
slow = slow.next
# reverse last half
slow.next = reverse(slow.next)
# reorder
p1, p2 = head, slow.next
slow.next = None
while p1 != slow.next and p2:
p1n, p2n = p1.next, p2.next
p1.next = p2
p2.next = p1n
p1, p2 = p1n, p2n
return ret_head.next