「前端刷题」24. 两两交换链表中的节点

263 阅读2分钟

这是我参与8月更文挑战的第24天,活动详情查看:8月更文挑战

题目

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

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

 

示例 1:

输入: head = [1,2,3,4]

输出:[2,1,4,3]

示例 2:

输入: head = []

输出:[]

示例 3:

输入: head = [1]

输出:[1]

 

提示:

  • 链表中节点的数目在范围 [0, 100]
  • 0 <= Node.val <= 100 

**进阶:**你能在不修改链表节点值的情况下解决这个问题吗?(也就是说,仅修改节点本身。)

解题思路

思路1

  • 设置虚拟头结点 dummy,因为真实头结点要换人,设置了 dummy 后,dummy.next 就能找到头结点。
  • 开启 while 循环,一对结点的交换有三个指针要改变,见下图。
  • 指针推进,准备交换下一对结点。
  • 最后返回 dummy.next 。

image.png

代码

const swapPairs = (head) => {
  const dummy = new ListNode(0);
  dummy.next = head;
  let prev = dummy;

  while (head && head.next) {
    const next = head.next; // 临时保存head.next,因为head.next待会要改变
    head.next = next.next;
    next.next = head;
    prev.next = next;  

    prev = head;      // 指针更新
    head = head.next; // 指针更新
  }
  return dummy.next;
};

思路2,非递归

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)
  • 思路
  • 添加一个哨兵节点
  • 三个节点外加一个哨兵节点之间作指针指向变换操作
  • 图解
  • 截屏2019-12-19上午7.16.40.png
/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var swapPairs = function(head) {
    let thead = new ListNode(0);
    thead.next = head;
    let tmp = thead;
    while(tmp.next != null && tmp.next.next != null){
        let start = tmp.next;
        let end = start.next;
        tmp.next = end;
        start.next = end.next;
        end.next = start;
        tmp = start;
    }
    return thead.next;
};

思路3,递归

  • 时间复杂度:O(n)
  • 空间复杂度:O(n)
  • 思路
  • 终止
    • 同解法一:至少三个节点之间才可以互换
    • 只有一个节点或没有节点,返回此节点
  • 交换
    • 设需要交换的两个节点为head、next
    • head -> next -> c -> ...
    • head -> c -> ... && next -> head
    • next -> head -> c -> ...
      • head 连接( -> )后面交换完成的子链表
      • next 连接( -> )head 完成交换
    • 对子链表重复上述过程即可
/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var swapPairs = function(head) {
    if(head == null || head.next == null){
        return head;
    }
    // 获得第 2 个节点
    let next = head.next;
    // next.next = head.next.next
    // 第1个节点指向第 3 个节点,并从第3个节点开始递归
    head.next = swapPairs(next.next);
    // 第2个节点指向第 1 个节点
    next.next = head;
    // 或者 [head.next,next.next] = [swapPairs(next.next),head]
    return next;
};

最后

曾梦想仗剑走天涯

看一看世界的繁华

年少的心总有些轻狂

终究不过是个普通人

无怨无悔我走我路

「前端刷题」No.24