链表中等2 种解法

#24两两交换链表中的节点

不修改节点值,将单链表中每两个相邻节点交换。

#链表#递归#迭代

解题主线

01

哨兵节点让首对节点的交换与后续节点对使用同一套重连逻辑。

02

递归中第二个节点成为当前段新头,第一个节点连接已交换完成的后缀。

解法 1迭代重连

让 previous 指向每一对节点的前驱,交换后移动到该对的新尾部。

时间复杂度

O(n)

空间复杂度

O(1)

24. 两两交换链表中的节点 · 迭代重连
final class ListNode {
    int val;
    ListNode next;

    ListNode(int val) {
        this.val = val;
    }

    ListNode(int val, ListNode next) {
        this.val = val;
        this.next = next;
    }
}

final class Solution {
    public ListNode swapPairs(ListNode head) {
        ListNode dummy = new ListNode(0, head);
        ListNode previous = dummy;
        while (previous.next != null && previous.next.next != null) {
            ListNode first = previous.next;
            ListNode second = first.next;
            first.next = second.next;
            second.next = first;
            previous.next = second;
            previous = first;
        }
        return dummy.next;
    }
}

让 previous 指向每一对节点的前驱,交换后移动到该对的新尾部。

解法 2递归交换

先递归交换第二个节点之后的链表,再翻转当前两个节点的连接。

时间复杂度

O(n)

空间复杂度

O(n),递归栈

24. 两两交换链表中的节点 · 递归交换
final class ListNode {
    int val;
    ListNode next;

    ListNode(int val) {
        this.val = val;
    }

    ListNode(int val, ListNode next) {
        this.val = val;
        this.next = next;
    }
}

final class Solution {
    public ListNode swapPairs(ListNode head) {
        if (head == null || head.next == null) return head;
        ListNode second = head.next;
        head.next = swapPairs(second.next);
        second.next = head;
        return second;
    }
}

先递归交换第二个节点之后的链表,再翻转当前两个节点的连接。

边界与易错点

  • 重连前先保存两个节点引用,避免修改 next 后丢失后缀。
  • 奇数长度链表的最后一个节点保持原位。
整理来源

由旧仓库源码复核、去重并整理;展示代码已按 Java 21 语义修正明显问题。

medium/Q024_swapPairs.java