返回

路飞的算法修炼之路:剑指 143. 重排链表

前端

写在前面

大家好,我是路飞,一个热爱算法的前端摸鱼老。今天,我将与大家分享一道算法题 —— LeetCode 143. 重排链表。

这道题看似简单,实则暗藏玄机。为了让大家更好地理解重排链表的精妙之处,我将使用双指针技术,提供一种清晰易懂的解题思路。话不多说,让我们一起扬帆起航,踏上算法修炼的征途!

题目解析

题目:

给定一个单链表 L: L0 → L1 → … → Ln-1 → Ln ,将其重排为: L0 → Ln → L1 → Ln-1 → L2 → Ln-2 → …

示例:

给定链表:1->2->3->4,重排后得到:1->4->2->3。

思路导引

这道题的核心在于理解重排链表的本质。重排链表的目的是将链表中的偶数项(从 0 开始计数)全部移到奇数项的后面。

我们可以使用双指针技术来实现这一目标:

  1. 创建两个指针 :slow 和 fast,slow 指针每次移动一步,fast 指针每次移动两步。
  2. 当 fast 指针到达链表末尾时 ,slow 指针指向链表中点。
  3. 将 slow 指针指向的中点节点作为分界点 ,将链表拆分为两部分。
  4. 对后一部分链表进行逆置操作
  5. 将逆置后的后一部分链表插入到前一部分链表中

代码实现

def reorderList(self, head: Optional[ListNode]) -> None:
    if not head or not head.next:
        return
    
    slow, fast = head, head.next
    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next
    
    second = slow.next
    prev = slow.next = None
    while second:
        nxt = second.next
        second.next = prev
        prev = second
        second = nxt
    
    first, second = head, prev
    while second:
        nxt1, nxt2 = first.next, second.next
        first.next = second
        second.next = nxt1
        first, second = nxt1, nxt2

时间复杂度:

O(n),其中 n 为链表的长度。

空间复杂度:

O(1),因为我们没有使用额外的空间。

总结

通过使用双指针技术,我们可以轻松解决 LeetCode 143. 重排链表 这道算法题。理解重排链表的本质至关重要,它将引导我们找到最优的解题思路。

算法修炼之路漫漫其修远,希望这道题的讲解能帮助大家提升算法思维。让我们继续前行,不断探索算法的奥秘,提高逼格,成为一名合格的摸鱼老!

附录

拓展练习:

  1. 尝试使用递归的方法解决这道题。
  2. 如果链表中存在环,如何处理?
  3. 如何优化代码,使其时间复杂度达到 O(log n)?

参考链接:

LeetCode 143. 重排链表