143. 重排链表
题意
给定一个单链表 L:L0→L1→…→L**n-1→Ln , 将其重新排列后变为: L0→L**n→L1→L**n-1→L2→L**n-2→…
并且需要实际的进行节点交换;
解题思路
拆分成两条链表:
找到中间的结点;
将链表拆分成左右两条链表,并且将右边的链表进行反转;
将左右两条链表进行合并;
双端队列:
将链表结点加入到队列中;
将从左边取出的结点和右边取出的结点进行连接;
这里需要注意的是虽然说是右边结点在左边结点的前面,但是左边链表的结点是在第一个位置的,比如[1, 2, 3, 4],最后的结果应该是1->4->2->3,这里的1是在第一个的位置,而不是4;
实现
class Solution(object):
def reorderList(self, head):
"""
执行用时 : 160 ms, 在Reorder List的Python提交中击败了14.77% 的用户
内存消耗 : 28.8 MB, 在Reorder List的Python提交中击败了11.11% 的用户
:type head: ListNode
:rtype: None Do not return anything, modify head in-place instead.
"""
if not head or not head.next:
return
# 1. 找到中间的结点
slow, fast = head, head
while fast.next and fast.next.next:
slow = slow.next
fast = fast.next.next
# 2. 将链表拆分成两部分,并且将右边的链表反转
rev_head = self.reverse_node(slow.next)
slow.next = None
# 3. 将两个链表进行合并
slow, fast = head, rev_head
while slow and fast:
# 分别保存下两条链表的下一个结点的位置
next_slow = slow.next
next_fast = fast.next
# 左边链表的起始结点指向右边链表的起始结点
slow.next = fast
# 右边链表的起始结点的指向左边链表的下一个结点
fast.next = slow.next
slow = next_slow
fast = next_fast
def reverse_node(self, head):
"""
将链表反转
:param head:
:return:
"""
prev_node, cur_node, next_node = None, head, head.next
while cur_node:
next_node = cur_node.next
cur_node.next = prev_node
prev_node = cur_node
cur_node = next_node
return prev_node
def reorderList2(self, head):
"""
执行用时 : 184 ms, 在Reorder List的Python提交中击败了4.55% 的用户
内存消耗 : 28.8 MB, 在Reorder List的Python提交中击败了11.11% 的用户
:type head: ListNode
:rtype: None Do not return anything, modify head in-place instead.
"""
from collections import deque
if not head or not head.next:
return
tmp = head
queue = deque()
while tmp:
queue.append(tmp)
tmp = tmp.next
while queue:
# 如果不存在说明是起始结点,否则连接左边结点
if not tmp:
tmp = queue.popleft()
else:
tmp.next = queue.popleft()
tmp = tmp.next
if queue:
# 和右边结点进行连接
tmp.next = queue.pop()
tmp = tmp.next
tmp.next = None