LeetCode热题(JS版) - 24. 两两交换链表中的节点

71 阅读2分钟

题目描述

给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。

你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

示例:

给定 1->2->3->4, 你应该返回 2->1->4->3.

解题思路

这道题可以使用递归和迭代两种方法来解决。

方法一:递归

对于给定的链表,我们可以通过递归的方式将其两两交换。递归函数的作用就是返回已经交换完的子链表。

具体步骤如下:

  1. 设当前要交换的两个节点为 headnext
  2. next 的下一个节点调用递归函数并接收返回值作为 head 的下一个节点。
  3. head 的下一个节点指向递归返回的节点(即 next)。
  4. next 的下一个节点指向 head
  5. 返回 next

最终,我们可以得到交换完成后的链表。

方法二:迭代

另外一种解法是使用迭代。我们可以分别处理每两个相邻的节点,然后将其交换位置。

具体步骤如下:

  1. 创建一个假的头结点 dummy 并将其指向链表的头结点。
  2. 定义节点 predummy
  3. 当链表中至少还剩两个节点时,定义节点 firstpre.next,节点 secondfirst.next
  4. pre 的下一个节点指向 second
  5. first 的下一个节点指向 second.next
  6. second 的下一个节点指向 first
  7. pre 指向已交换过的链表部分的末尾节点(即 first)。
  8. 重复步骤 3-7 直到链表中的所有节点都被交换完毕。

最终,我们可以得到交换完成后的链表。

代码实现

方法一:递归

function swapPairs(head: ListNode | null): ListNode | null {
  if (head === null || head.next === null) {
    return head;
  }
  // a -> b -> c -> d
  const next = head.next; // b
  head.next = swapPairs(next.next);// 递归交换 a -> (交换d -> c)
  
  next.next = head; // b -> a

  return next;// b -> a -> (d -> c)
}

方法二:迭代

function swapPairs(head: ListNode | null): ListNode | null {
  // a -> b -> c -> d
  
  // 虚拟节点
  const dummy = new ListNode(-1);
  dummy.next = head; // () -> a
  
  let pre = dummy;
  while (pre.next !== null && pre.next.next !== null) {
    const first = pre.next;// a
    const second = first.next;// b

    pre.next = second;// () -> b
    first.next = second.next;// a -> c
    second.next = first;// b -> a

    pre = first;// () = a 后移
  }

  return dummy.next;// () -> b -> a ...
}

时间/空间复杂度

  • 时间复杂度:O(n)O(n),其中 nn 是链表中的节点数。需要遍历链表中的所有节点。
  • 空间复杂度:O(n)O(n),递归方法需要内存空间来维护递归栈,而迭代方法需要额外的常量级空间来维护指针和辅助节点。