LeetCode从算法到算命—24.两两交换链表中的节点(20230806)
24.两两交换链表中的节点
题目信息
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
示例 1:
输入:head = [1,2,3,4]
输出:[2,1,4,3]
示例 2:
输入:head = []
输出:[]
示例 3:
输入:head = [1]
输出:[1]
提示:
- 链表中节点的数目在范围
[0, 100]
内 0 <= Node.val <= 100
解题思路
在不修改值的情况下完成本题,也就是不能把整个链表每个值放到集合里,在集合中两两交换后再构建为一个新的链表。我们需要直接对节点本身进行交换,而不能改变每个节点的值。
每次只交换两个节点,假设这样一个链表1 -> 2 -> 3 -> 4 -> 5
,交换一次之后就会变成2 -> 1
3 -> 4 -> 5
,再接下来交换以3
开头的链表2 -> 1
4 -> 3
5
,最后以5
开头的链表后面是没有元素的,也就是无法交换的。交换完之后把它们连起来,就是最后的答案了,因此这道题目可以用递归来解决。
指针的变化情况是,第一次交换的时候,二号节点指向一号节点,也就是Node2.next指向Node1;一号节点没有指向二号节点,而是以三号节点为开头的链表交换后的结果(交换后是返回一个头节点来表示整个链表),因此Node1应该指向swap(Node3)。那么重复这个过程就能达到两两节点交换的效果,最后返回二号节点(因为交换后二号节点就会变成整个链表的头节点)就可以了。
Java代码
public class Solution {
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; }
}
public ListNode swapPairs(ListNode head) {
//如果链表没有节点了或者只剩一个节点,就不用交换了,直接返回当前节点
if (head == null || head.next == null) {
return head;
}
//定义三个节点
ListNode node1 = head;
ListNode node2 = node1.next;
ListNode node3 = node2.next;
//两两交换中,原第二个节点指向第一个节点
node2.next = node1;
//两两交换中,原第一个节点指向三号节点->以三号节点开头的链表交换后的结果
node1.next = swapPairs(node3);
//最后返回node2
return node2;
}
}