143. 重排链表
原始题目链接:https://leetcode-cn.com/problems/reorder-list/
解题思路:
观察最后重排链表的结果发现,就是将链表的左半部分和翻转后的右半部分进行了合并后的结果。所以根据这个结果,可以先找到原始链表的中间节点,将链表一分为二,然后将右边部分的链表翻转,再合并两个链表,具体来说,合并是交叉合并的顺序,所以最终的解法可以分为3个步骤,具体实现开代码及注释。
- 找原始链表的中间节点;
- 将右边部分的链表翻转;
- 交叉合并两个链表。
代码实现:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
# 查找链表中间节点的函数,返回中间节点
def find_middle_node(self, head: ListNode)-> ListNode:
# 利用快慢指针来查找
fast, slow = head, head
while fast.next and fast.next.next:
fast = fast.next.next
slow = slow.next
return slow
# 翻转链表的函数,返回翻转后的链表的头结点
def reverse_listnode(self, head: ListNode)-> ListNode:
pre = None
cur = head
while cur:
cur_next_node = cur.next
cur.next = pre
pre = cur
cur = cur_next_node
# pre最后指向了翻转后的链表的头部节点
return pre
# 合并两个链表的函数
def merger_two_listnodes(self, l1: ListNode, l2: ListNode):
# 根据题意,其实是交叉合并两个链表的节点
# l1是原始链表的左半部分,l2是翻转后的原始链表的右半部分
while l1 and l2:
# 先保存各自链表当前节点的下一个节点,不然修改了当前节点后找不到下一个节点
l1_next_node = l1.next
l2_next_noed = l2.next
# 开始交叉合并
# 根据题意,l1的下一个节点是翻转后的l2节点
l1.next = l2
# l1这个指针指向l1的下一个节点,为了后续操作l1链表
l1 = l1_next_node
# 根据题意,l2的下一个节点是l1的下一个节点
l2.next = l1
# l2指针指向l2的下一个节点
l2 = l2_next_noed
def reorderList(self, head: ListNode) -> None:
"""
Do not return anything, modify head in-place instead.
"""
# 先找中间节点,把原始链表分为两部分
mid_node = self.find_middle_node(head)
# l1是左边部分,l2是右边部分
l1 = head
l2 = mid_node.next
# 分好后,根据题意,中间节点是最后重排链表的尾节点,所以next域为空
# 必须在分好后,将mid_node的next域置空
mid_node.next = None
# 将右边部分翻转
l2 = self.reverse_listnode(l2)
# 合并两个链表
self.merger_two_listnodes(l1, l2)
参考文献:
https://leetcode-cn.com/problems/reorder-list/solution/zhong-pai-lian-biao-by-leetcode-solution/