返回

解剖 Leetcode 24:巧妙交换,重塑单向循环流转

前端

问题概述

给定一个单向循环流转的节点,你的任务是两两交换其相邻节点,并返回交换后的循环流转的节点。请注意,你不可以直接修改节点值,而需要实际进行节点交换操作。

哨兵巧思

直观地,我们可以采用暴力法,对相邻节点逐一交换。然而,这种方法需要遍历整个循环流转的节点,在最坏情况下复杂度达到 O(n),其中 n 为节点数量。

聪明的算法设计者们引入了一个巧妙的概念:哨兵。哨兵是一个虚拟的节点,它指向第一个有效节点,且其 next 指针指向最后一个有效节点。有了哨兵,我们可以轻松地实现两两交换操作,因为我们只需要处理哨兵的 next 指针即可。

算法流程

以下是算法的详细流程:

  1. 初始化哨兵: 建立一个哨兵节点,使其指向第一个有效节点,并将其保存为头指针。
  2. 循环遍历: 以哨兵为起点,遍历整个循环流转的节点。
  3. 交换相邻节点: 对于每个节点,将其与后继节点交换。
  4. 更新头指针: 将哨兵的 next 指针更新为交换后的第一个节点。
  5. 终止条件: 当哨兵的 next 指针指向第一个有效节点时,算法结束。

代码实现

def swapPairs(head):
    if not head or not head.next:
        return head

    dummy = ListNode(0)
    dummy.next = head

    prev = dummy
    current = head

    while current and current.next:
        nextPair = current.next.next
        second = current.next
        
        prev.next = second
        current.next = nextPair
        second.next = current
        
        prev = current
        current = nextPair
    
    return dummy.next

复杂度分析

在最坏情况下,算法需要遍历整个循环流转的节点,因此时间复杂度为 O(n)。空间复杂度为 O(1),因为我们只引入了一个哨兵节点。

总结

两两交换单向循环流转的节点问题,看似复杂,但通过巧妙的哨兵设计,我们可以将其简化为对哨兵 next 指针的巧妙操作。这体现了算法设计中的灵活思维,通过引入一个虚拟的哨兵节点,可以简化问题,提高算法效率。