这是我参与8月更文挑战的第24天,活动详情查看:8月更文挑战
题目
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例 1:
输入: head = [1,2,3,4]
输出:[2,1,4,3]
示例 2:
输入: head = []
输出:[]
示例 3:
输入: head = [1]
输出:[1]
提示:
- 链表中节点的数目在范围
[0, 100]内 0 <= Node.val <= 100
**进阶:**你能在不修改链表节点值的情况下解决这个问题吗?(也就是说,仅修改节点本身。)
解题思路
思路1
- 设置虚拟头结点 dummy,因为真实头结点要换人,设置了 dummy 后,dummy.next 就能找到头结点。
- 开启 while 循环,一对结点的交换有三个指针要改变,见下图。
- 指针推进,准备交换下一对结点。
- 最后返回 dummy.next 。
代码
const swapPairs = (head) => {
const dummy = new ListNode(0);
dummy.next = head;
let prev = dummy;
while (head && head.next) {
const next = head.next; // 临时保存head.next,因为head.next待会要改变
head.next = next.next;
next.next = head;
prev.next = next;
prev = head; // 指针更新
head = head.next; // 指针更新
}
return dummy.next;
};
思路2,非递归
- 时间复杂度:O(n)
- 空间复杂度:O(1)
- 思路
- 添加一个哨兵节点
- 三个节点外加一个哨兵节点之间作指针指向变换操作
- 图解
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var swapPairs = function(head) {
let thead = new ListNode(0);
thead.next = head;
let tmp = thead;
while(tmp.next != null && tmp.next.next != null){
let start = tmp.next;
let end = start.next;
tmp.next = end;
start.next = end.next;
end.next = start;
tmp = start;
}
return thead.next;
};
思路3,递归
- 时间复杂度:O(n)
- 空间复杂度:O(n)
- 思路
- 终止
- 同解法一:至少三个节点之间才可以互换
- 只有一个节点或没有节点,返回此节点
- 交换
- 设需要交换的两个节点为head、next
- head -> next -> c -> ...
- head -> c -> ... && next -> head
- next -> head -> c -> ...
- head 连接( -> )后面交换完成的子链表
- next 连接( -> )head 完成交换
- 对子链表重复上述过程即可
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var swapPairs = function(head) {
if(head == null || head.next == null){
return head;
}
// 获得第 2 个节点
let next = head.next;
// next.next = head.next.next
// 第1个节点指向第 3 个节点,并从第3个节点开始递归
head.next = swapPairs(next.next);
// 第2个节点指向第 1 个节点
next.next = head;
// 或者 [head.next,next.next] = [swapPairs(next.next),head]
return next;
};
最后
曾梦想仗剑走天涯
看一看世界的繁华
年少的心总有些轻狂
终究不过是个普通人
无怨无悔我走我路
「前端刷题」No.24