今天做 LeetCode 24.两两交换链表中的节点,难度为 Medium。
一. 题目要求
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
示例:
Given 1->2->3->4, you should return the list as 2->1->4->3.
二. 解题思路 & 代码
这道题难点在于搞清楚交换过程中节点指针的变化情况,解题时最好在纸上用图把交换过程画出来,每次交换都要涉及下面四个节点,如图:
- Pre 节点:当前节点 A 的前一个节点,交换后其 next 指向 B
- A 节点:要交换的节点,交换后 其 next 指向 Next
- B 节点:要交换的 A 节点的 next 节点,交换后其 next 指向 A。
- Next 节点:B 节点的 next 节点,交换完成作为下一次交换的节点,继续遍历。
明确了每次交换的几个节点,解题逻辑也就比较清楚了:
- 1.拿到 B 和 Next
ListNode B = A.next;
ListNode nextNode = B.next.
- 2.将 B 指向 A,将 A 指向 B.next
B.next = A;
A.next = nextNode.
-
- 如果有 preNode,那么需要将其指向 B
if (preNode != null) {
preNode.next = B;
}
- 4.交换完成后更新 preNode 和 A,进行下一次的遍历交换
preNode = A;
A = nextNode;
对照着图将思路搞清楚,代码也就好写了。
具体完整实现代码如下:
class Solution {
public ListNode swapPairs(ListNode head) {
if(head == null) {
return null;
}
if(head.next == null) {
return head;
}
ListNode result = head.next;
// 最开始 pre 节点为空
ListNode preNode = null;
// 从 header 节点开始
// 因为是两两交换,因此要判断 node 和 node.next 都不为空才行
ListNode node = head;
while(node != null && node.next != null) {
// 当前节点的 next 节点
ListNode next = node.next;
// 当前节点的 next.next 节点
// 事先记录下来作为下一个要遍历交换的节点
ListNode tmpNextNode = next.next;
// 交换节点
// 将 B 指向 A
next.next = node;
// 将 A 指向 Next
node.next = tmpNextNode;
// preNode 不为空的话,需要将 PreNode.next 指向 B
if(preNode != null) {
preNode.next = next;
}
// 新的 preNode 和 node
preNode = node;
node = tmpNextNode;
}
return result;
}
}
三. 解题后记
解题思路挺好想的,不算难,但是交换过程中各个节点的变换是非常容易搞混的,面对这种题目最好的方式就是画图,把各个节点的位置变换用图画清楚,写起来思路也就不容易乱了。