leetcode刷题日记-【24. 两两交换链表中的节点】

101 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第20天,点击查看活动详情

题目描述

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

 

示例 1:

image.png 输入:head = [1,2,3,4] 输出:[2,1,4,3] 示例 2:

输入:head = [] 输出:[] 示例 3:

输入:head = [1] 输出:[1]  

提示:

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

题目元素

  • 给定一个链表,交换相邻链表节点,返回新的链表

解题思路

交换链表中的节点元素实际上考察的还是三个要点。哑元节点、虚拟节点和链表移动。

哑元节点已经在前面的题解中有过描述,它的主要目的就是将所有节点做统一处理,可以把它看成分数通分,通过设置一个空的前置节点使首节点可以和其它节点统一处理,降低代码复杂度。

虚拟节点,一般将虚拟节点用来指向当前操作节点,随着链表移动一直指向最新的节点,可以方便地进行节点的操作;

链表移动,链表是通过移动next来进行移动的,所以实质上就是将每次将当前操作节点设置成上一次操作节点的next,就可以实现链表的移动。

代码基本结构为

// 设置哑元节点
// 设置虚拟节点
while(root!=null){
    // 链表操作
    // 链表移动
    // 虚拟节点设置
}
  • 先设置哑元节点dummyNode,它的next节点指向真实的链表。
  • 设置虚拟节点初始值赋值为dummyNode,因为第一次遍历对象应该为链表的第一个元素;
  • 循环root节点,交换虚拟节点next与其后面节点
  • 将虚拟节点的值赋值为当前节点

代码实现

/**
 * @param head
 * @return
 */
public ListNode swapPairs(ListNode head) {
    // 设定哑元节点
    ListNode dummyNode = new ListNode();
    dummyNode.next = head;
    // 设置虚拟节点
    ListNode tailNode = dummyNode;
    while (tailNode.next != null && tailNode.next.next != null) {
        // 注意这里移动的对象是tailNode,tailNode一直指向的是当前操作节点的头节点
        // 停止条件是需要交换的两个元素都不为空,如果其中一个为空就没有交换的必要了
        // 需要交换的头一个元素
        ListNode node1 = tailNode.next;
        // 需要交换的后一个元素
        ListNode node2 = tailNode.next.next;
        // 交换两个元素的位置
        tailNode.next = node2;
        // 这两个对象都是引用对象类型,所以这里修改的都是链表内节点的next对象
        node1.next = node2.next;
        node2.next = node1;
        tailNode = node1;
    }
    return dummyNode.next;
}