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

迭代

解题思路

  1. 创建哑结点 dummyHeaddummyHead.next = headtemp 表示当前到达的节点,初始时 temp = dummyHead,每次需要交换 temp 后面的两个节点;

  2. 如果 temp 的后面没有节点或者只有一个节点,则没有更多的节点需要交换,因此结束交换;

  3. 否则,获得 temp 后面的两个节点 node1node2 通过更新节点的指针关系实现两两交换节点;

图解

复杂度

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

  2. 空间复杂度:O(1)

代码实现

var swapPairs = function (head) {
    const dmy = new ListNode(0, head);
    // 定义 tmp 当前指针
    let tmp = dmy;

    while (tmp.next !== null && tmp.next.next !== null) {
        // 定义 node1 和 node2 指针
        let node1 = tmp.next;
        let node2 = tmp.next.next;

        // 反转 node1 node2 指向
        tmp.next = node2;
        node1.next = node2.next;
        node2.next = node1;

        // 移动 tmp 指针
        tmp = tmp.next.next
    }

    return dmy.next;
};

头递归

图解

复杂度

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

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

实现代码

var swapPairs = function (head) {
    if (head === null || head.next === null) return head;

    let node1 = head.next;
    let node2 = head.next.next;
    node1.next = head; // 反转
    head.next = swapPairs(node2);

    return node1; // 返回交换完成的子链表
};

尾递归

图解

复杂度

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

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

代码实现

var swapPairs = function (head) {
    if (head === null || head.next === null) return head;

    let nextNode = head.next;
    head.next = swapPairs(head.next.next); // 当前节点指向下下个节点
    nextNode.next = head; // 下下个节点指向下个节点

    return nextNode; // 返回交换完成的子链表
};

参考资料

  1. 卡尔:《代码随想录》

打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于前端开发的技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程。

了解更多

目录

  1. 1. 迭代
    1. 1.1. 解题思路
    2. 1.2. 图解
    3. 1.3. 复杂度
    4. 1.4. 代码实现
  2. 2. 头递归
    1. 2.1. 图解
    2. 2.2. 复杂度
    3. 2.3. 实现代码
  3. 3. 尾递归
    1. 3.1. 图解
    2. 3.2. 复杂度
    3. 3.3. 代码实现
  4. 4. 参考资料