24. 两两交换链表中的节点
链接:https://leetcode-cn.com/problems/swap-nodes-in-pairs/
题目描述见链接内容。
解法1:迭代
一开始想用双指针解决,结果把两个指针一顿交换,发现交换了个寂寞,后来发现只利用一个指针cur
,对cur.next
和cur.next.next
不断赋值就可以
还利用之前的小技巧,声明了一个DummyNode,放在head
前面,这样就不需要判断首节点的特殊性了
var swapPairs = function (head) {
// 在 head 之前声明一个DummyNode
const dummyNode = new ListNode();
dummyNode.next = head;
let cur = dummyNode;
// dummyNode head node1 node2 node3....
while (cur && cur.next && cur.next.next) {
// cur 指向 dummyNode, next 变量指向 node2
const next = cur.next && cur.next.next ? cur.next.next.next : null,
// prev 指向 head
prev = cur.next;
// 将 dummyNode.next 指向 node1
cur.next = cur.next ? cur.next.next : null;
// 将新的 node1.next 指向 head,实现了换位
cur.next.next = prev;
// 将换位后的 head.next 指向 node2,把断开的链表又练了起来
cur.next.next.next = next;
// 指针需要向前移动两位
cur = cur.next ? cur.next.next : null;
}
return dummyNode.next;
};
- 时间复杂度:
${O(N)}$
- 空间复杂度:
${O(1)}$
- 执行用时:68ms, 在所有JavaScript提交中击败了95%的用户,内存消耗:37.7MB,在所有JavaScript提交中击败了91%的用户
解法2:递归
为什么我总是想不到递归的解法,看了题解发现又很简单,可以参考这篇文章,好好学习一下递归
关于这道题的解决,只要参考下面一张图就能够搞明白了:
var swapPairs = function (head) {
if (!head || !head.next) {
return head;
}
// 原来的后面的节点
const next = head.next;
// head 移动到后面后,需要连接的已处理完成的节点
head.next = swapPairs(next.next);
// 将 next 移动到 head 前面
next.next = head;
// 返回的是已处理好的节点
return next;
};
- 时间复杂度:
${O(N)}$
- 空间复杂度:
${O(N)}$
- 执行用时:60ms, 在所有JavaScript提交中击败了99.51%的用户,内存消耗:37.8MB,在所有JavaScript提交中击败了88%的用户
解法3:栈
完全参考官方解答,自己没有这个脑子,因为我是猪脑子
可以把两个链表的比较操作,改为递归过程,就是两个链表头部值较小的一个节点与剩下元素的merge
操作结果合并,代码还是挺好理解的:
var mergeTwoLists = function (l1, l2) {
if (!l1) {
return l2;
}
if (!l2) {
return l1;
}
if (l1.val < l2.val) {
l1.next = mergeTwoLists(l1.next, l2);
return l1;
}
l2.next = mergeTwoLists(l1.next, l2);
return l2;
};
- 时间复杂度:
${O(m+n)}$
- 空间复杂度:
${O(m+n)}$
- 执行用时:92ms, 在所有JavaScript提交中击败了76.44%的用户,内存消耗39.5MB,在所有JavaScript提交中击败了33.39%的用户