题目描述
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例:
给定 1->2->3->4, 你应该返回 2->1->4->3.
解题思路
这道题可以使用递归和迭代两种方法来解决。
方法一:递归
对于给定的链表,我们可以通过递归的方式将其两两交换。递归函数的作用就是返回已经交换完的子链表。
具体步骤如下:
- 设当前要交换的两个节点为
head和next。 - 对
next的下一个节点调用递归函数并接收返回值作为head的下一个节点。 - 将
head的下一个节点指向递归返回的节点(即next)。 - 将
next的下一个节点指向head。 - 返回
next。
最终,我们可以得到交换完成后的链表。
方法二:迭代
另外一种解法是使用迭代。我们可以分别处理每两个相邻的节点,然后将其交换位置。
具体步骤如下:
- 创建一个假的头结点
dummy并将其指向链表的头结点。 - 定义节点
pre为dummy。 - 当链表中至少还剩两个节点时,定义节点
first为pre.next,节点second为first.next。 - 将
pre的下一个节点指向second。 - 将
first的下一个节点指向second.next。 - 将
second的下一个节点指向first。 - 将
pre指向已交换过的链表部分的末尾节点(即first)。 - 重复步骤 3-7 直到链表中的所有节点都被交换完毕。
最终,我们可以得到交换完成后的链表。
代码实现
方法一:递归
function swapPairs(head: ListNode | null): ListNode | null {
if (head === null || head.next === null) {
return head;
}
// a -> b -> c -> d
const next = head.next; // b
head.next = swapPairs(next.next);// 递归交换 a -> (交换d -> c)
next.next = head; // b -> a
return next;// b -> a -> (d -> c)
}
方法二:迭代
function swapPairs(head: ListNode | null): ListNode | null {
// a -> b -> c -> d
// 虚拟节点
const dummy = new ListNode(-1);
dummy.next = head; // () -> a
let pre = dummy;
while (pre.next !== null && pre.next.next !== null) {
const first = pre.next;// a
const second = first.next;// b
pre.next = second;// () -> b
first.next = second.next;// a -> c
second.next = first;// b -> a
pre = first;// () = a 后移
}
return dummy.next;// () -> b -> a ...
}
时间/空间复杂度
- 时间复杂度:,其中 是链表中的节点数。需要遍历链表中的所有节点。
- 空间复杂度:,递归方法需要内存空间来维护递归栈,而迭代方法需要额外的常量级空间来维护指针和辅助节点。