📜  就地重新排列给定的链表。(1)

📅  最后修改于: 2023-12-03 15:25:23.361000             🧑  作者: Mango

就地重新排列给定的链表

问题描述

给定一个单链表,按如下规则重新排列链表:

  • 将链表的尾节点指向第二个节点(原链表的最后一个节点成为新链表的第二个节点);
  • 将第二个节点指向倒数第三个节点;
  • 依此类推,重复步骤,直到重新排列整个链表。
解决方法
  1. 找到链表的中间节点。
  2. 反转链表的后半部分。
  3. 将链表的前半部分和后半部分依次合并。
找到链表的中间节点

可以使用快慢指针的方法找到链表的中间节点。快指针一次移动两个节点,慢指针一次移动一个节点,当快指针到达链表的末尾时,慢指针刚好到达了链表的中间。

def find_middle_node(head):
    slow_ptr = head
    fast_ptr = head
    
    while fast_ptr.next and fast_ptr.next.next:
        slow_ptr = slow_ptr.next
        fast_ptr = fast_ptr.next.next
    
    return slow_ptr
反转链表的后半部分

使用三个指针,分别指向当前节点、前驱节点和后继节点,依次遍历链表并反转指针指向。

def reverse_list(head):
    prev_ptr = None
    curr_ptr = head
    
    while curr_ptr:
        next_ptr = curr_ptr.next
        curr_ptr.next = prev_ptr
        prev_ptr = curr_ptr
        curr_ptr = next_ptr
    
    return prev_ptr
合并链表的前半部分和后半部分

依次遍历链表的前半部分和后半部分,并将两个链表的节点交替合并。

def merge_lists(l1, l2):
    while l1 and l2:
        l1_next = l1.next
        l2_next = l2.next
        
        l1.next = l2
        l1 = l1_next
        
        l2.next = l1
        l2 = l2_next
完整代码
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def find_middle_node(head):
    slow_ptr = head
    fast_ptr = head
    
    while fast_ptr.next and fast_ptr.next.next:
        slow_ptr = slow_ptr.next
        fast_ptr = fast_ptr.next.next
    
    return slow_ptr

def reverse_list(head):
    prev_ptr = None
    curr_ptr = head
    
    while curr_ptr:
        next_ptr = curr_ptr.next
        curr_ptr.next = prev_ptr
        prev_ptr = curr_ptr
        curr_ptr = next_ptr
    
    return prev_ptr 

def merge_lists(l1, l2):
    while l1 and l2:
        l1_next = l1.next
        l2_next = l2.next
        
        l1.next = l2
        l1 = l1_next
        
        l2.next = l1
        l2 = l2_next

def reorder_list(head):
    if not head:
        return
    
    middle_node = find_middle_node(head)
    second_half_head = reverse_list(middle_node.next)
    middle_node.next = None
    
    merge_lists(head, second_half_head)

head = ListNode(1, ListNode(2, ListNode(3, ListNode(4, ListNode(5)))))

reorder_list(head)

while head:
    print(head.val)
    head = head.next
参考资料