题目描述
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
-
示例 1:
输入:head = [1,2,3,4]
输出:[2,1,4,3] -
示例 2:
输入:head = []
输出:[] -
示例 3:
输入:head = [1]
输出:[1]
提示:
链表中节点的数目在范围 [0, 100] 内
0 <= Node.val <= 100
进阶:你能在不修改链表节点值的情况下解决这个问题吗?(也就是说,仅修改节点本身。)
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/swap-nodes-in-pairs
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
空链表和只有一个节点的链表返回其本身即可。对于其它链表:
本人是用四个指针来进行交换(从前往后的顺序依次为abcd),其中ad是用于连接的指针(对于原链表而言,a是原链表头节点的前一个节点,也就是设定的伪节点,b节点才是头节点),bc是要做交换的指针,也就是把abcd变成acbd
这样一来代码就变成了
- a.next = c
- c.next = b
- b.next = d
为了方便后续遍历,还需还原abcd指针的顺序(注意只是指针的顺序,而不是指针所指向的元素的顺序)
- ListNode temp = c
- c = b
- b = temp
然后每次往后移动两个节点
- a = a.next.next
- b = b.next.next
- c = c.next.next
- d = d.next.next
在这种思路下,若在移动前发现d为null说明全部交换操作均已完成;若发现d.next为null说明d指向的元素为最后的奇数个元素,不用进行交换。这两种情况发生时,节点不用移动了,直接跳出循环。
代码详解
/**
* 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 pre = new ListNode(-1); // 伪节点
// 思路的四个指针
ListNode a = pre;
ListNode b = head;
ListNode c = head.next;
ListNode d = head.next.next;
while(true) {
// 完成交换
a.next = c;
c.next = b;
b.next = d;
if(d == null || d.next == null) { // 终止循环
break;
}
// 恢复指针abcd的顺序
ListNode temp = c;
c = b;
b = temp;
// 每次往后移动两个节点
a = a.next.next;
b = b.next.next;
c = c.next.next;
d = d.next.next;
}
return pre.next;
}
}
注意点
- 需先对d指针进行判断再往后移动两个节点,不然会导致空指针异常