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

222 阅读2分钟

题目介绍

力扣24题:leetcode-cn.com/problems/sw…

image.png

image.png

方法一:迭代

也可以通过迭代的方式实现两两交换链表中的节点。

创建哑结点 preHead,令 preHead.next = head。令 pre 表示当前到达的节点,初始时 pre = preHead。每次需要交换 pre 后面的两个节点。

如果 pre 的后面没有节点或者只有一个节点,则没有更多的节点需要交换,因此结束交换。否则,获得 pre 后面的两个节点 first 和 second,通过更新节点的指针关系实现两两交换节点。

具体而言,交换之前的节点关系是 temp -> first -> second,交换之后的节点关系要变成 temp -> second -> first,因此需要进行如下操作。

pre.next = second;
first.next = second.next;
second.next = first;

image.png

代码如下:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode swapPairs(ListNode head) {
        if(head == null || head.next == null) {
            return head;
        }
        ListNode preHead = new ListNode(-1);
        preHead.next = head;
        ListNode pre = preHead;
        ListNode first;
        ListNode second;
        while(pre.next != null && pre.next.next != null) {
            first = pre.next;//第一个元素
            second = first.next;//第二个元素
            pre.next = second;
            first.next = second.next;
            second.next = first;
            pre = pre.next.next;
        }
        return preHead.next;
    }
}

复杂度分析

  • 时间复杂度:O(n),其中 nn 是链表的节点数量。需要对每个节点进行更新指针的操作。
  • 空间复杂度:O(1)。

方法二:递归

可以通过递归的方式实现两两交换链表中的节点。

递归的终止条件是链表中没有节点,或者链表中只有一个节点,此时无法进行交换。

如果链表中至少有两个节点,则在两两交换链表中的节点之后,原始链表的头节点变成新的链表的第二个节点,原始链表的第二个节点变成新的链表的头节点。链表中的其余节点的两两交换可以递归地实现。在对链表中的其余节点递归地两两交换之后,更新节点之间的指针关系,即可完成整个链表的两两交换。

用 head 表示原始链表的头节点,新的链表的第二个节点,用 newHead 表示新的链表的头节点,原始链表的第二个节点,则原始链表中的其余节点的头节点是 newHead.next。令 head.next =swapPairs(newHead.next),表示将其余节点进行两两交换,交换后的新的头节点为 head 的下一个节点。然后令 newHead.next = head,即完成了所有节点的交换。最后返回新的链表的头节点 newHead。

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

复杂度分析

  • 时间复杂度:O(n),其中 n 是链表的节点数量。需要对每个节点进行更新指针的操作。

  • 空间复杂度:O(n),其中 n 是链表的节点数量。空间复杂度主要取决于递归调用的栈空间。