用JavaScript刷leetcode第24题-两两交换链表中的节点

443 阅读2分钟

前言

这题自己第一想法是K个一组翻转链表,K为2。
然后仔细想了下,没必要。如果用上述方法真的是简单问题复杂化了。
直接三个指针(分别指向已交换尾、待交换头、待交换尾) + 迭代就可以搞定。

一、题目描述

详细描述请看:leetcode的题目描述
大致描述:

  • 一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
  • 示例: image.png

二、解题

2.1 思路

  • 空链表、只有一个节点的链表不需要交换
  • 虚拟头节点:由于需要操作头节点的前一个节点,故需要虚头
  • 迭代,迭代继续的条件:为交换节点数大于2
  • 每次交换怎么交换? 看代码吧,其实就是头插法。将删掉的尾插到已完成交换的尾这句话算是交换重点。

2.2 代码

git代码地址

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */


const swapPairs = function (head) {
  // 空链表 、 只有一个节点的链表不需要交换
  if(head === null || head.next === null) return head

  // 虚拟头节点,需要操作头节点的前一个节点
  let dummy = new ListNode(-1, head)

  // 该指针每轮迭代都指向完成交换的尾部
  let pre = dummy

  // 迭代继续的条件,未交换节点数超过2
  while(pre.next && pre.next.next) {
    // first指向第一个节点、second指向第二个节点(这里的节点指即将两两交换的节点)
    let first = pre.next, second = pre.next.next
    
    // 接下来就是交换过程,三部走:second删、插

    // 删second
    first.next = second.next

    // 插second到pre后
    second.next = first
    pre.next = second

    // 以上已经完成交换, pre需要指向已完成交换的尾部
    pre = first
  }

  return dummy.next
}