24. 两两交换链表中的节点 - 力扣(LeetCode)
发布:2021年10月8日18:47:33
问题描述及示例
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例 1:
输入:head = [1,2,3,4]
输出:[2,1,4,3]
示例 2:
输入:head = []
输出:[]
示例 3:
输入:head = [1]
输出:[1]
提示:
链表中节点的数目在范围 [0, 100] 内
0 <= Node.val <= 100
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/swap-nodes-in-pairs
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
我的题解(双指针)
链表类的题目往往要用到指针。之前也碰到过链表相关的题,有关题解博客可参看下方【有关参考】处的链接。
本题也是利用了双指针的思路。
首先需要创建一个辅助头结点 dummy
,然后让指针 p
和 指针 q
完成将两个节点交换的任务。对于某两个节点的交换过程,可以参看下方动态图:
而之后的交换过程也是一样的。直到遇到 p === null
或 p.next === null
的情况。
值得一提的是,这次提交似乎是我第一次碰到击败 100% 用户的情况,不过LeetCode的判题结果和网络有一定关系,所以也不能全信,但是还是值得纪念一下。
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var swapPairs = function(head) {
// 如果链表为空,直接返回null
if(!head) {
return null;
}
// 创建辅助头结点dummy
let dummy = new ListNode(0,head);
// 初始化p、q指针的指向
let p = dummy;
let q = head;
// 开始交换两个相邻的节点,注意下面这个while循环的条件,只要 q 或者 q.next中有任何一方
// 为空,则停止循环。而且一定要将 q 放在前面,这是利用了 && 的短路特性,如果 q 为 null
// 的话,则直接判断整个条件为 false,于是跳出循环。如果将 q.next 放在前面的话,
// 如果 q 为 null,则 q.next 就会报错:
// 【TypeError: Cannot read property 'next' of null】
while(q && q.next) {
// 下面三句就是关键的交换两个相邻节点的逻辑,建议在图上自己动手画一画指针变化
p.next = q.next;
q.next = q.next.next;
p.next.next = q;
// 【tag1】下面三句用来移动p、q指针来为下一次交换做准备,可以简化为两句,详看下方优化
q = p.next;
q = q.next.next;
p = p.next.next;
}
// 最后返回头结点,注意不是辅助头结点
return dummy.next;
};
提交记录
55 / 55 个通过测试用例
状态:通过
执行用时:72 ms, 在所有 JavaScript 提交中击败了53.66%的用户
内存消耗:36.7 MB, 在所有 JavaScript 提交中击败了100.00%的用户
时间:2021/10/08 18:51
小小的优化
在【tag1】处的指针移动,其实可以把 q
指针【先往前走一步再往后走两步】的操作改成直【接让 q
指针往后走一步】:
// 原来的写法
...
q = p.next;
q = q.next.next;
p = p.next.next;
...
// 改进之后的写法
...
q = q.next;
p = p.next.next;
...
提交记录
55 / 55 个通过测试用例
状态:通过
执行用时:64 ms, 在所有 JavaScript 提交中击败了89.55%的用户
内存消耗:37.9 MB, 在所有 JavaScript 提交中击败了66.75%的用户
时间:2021/10/08 19:41
但是这个时间表现和空间表现和自己预想的结果好像还是有点出入,感觉这个结果和网络波动的因素关联挺大的……权当图个乐吧~
官方题解
更新:2021年7月29日18:43:21
因为我考虑到著作权归属问题,所以【官方题解】部分我不再粘贴具体的代码了,可到下方的链接中查看。
更新:2021年10月8日18:54:36
【更新结束】
有关参考
【此前做过的链表类题目】
更新:2021年10月8日20:17:10
参考:【算法-LeetCode】206. 反转链表(单链表;生成LeetCode单链表)_赖念安的博客-CSDN博客
参考:【算法-LeetCode】141. 环形链表(单链表;环;快慢指针;双指针)_赖念安的博客-CSDN博客
参考:【算法-剑指 Offer】22. 链表中倒数第k个节点(单链表;双指针)_赖念安的博客-CSDN博客
参考:【算法-LeetCode】160. 相交链表(双指针)_赖念安的博客-CSDN博客
参考:【算法-LeetCode】19. 删除链表的倒数第 N 个结点(双指针/快慢指针)_赖念安的博客-CSDN博客
参考:【算法-LeetCode】19. 删除链表的倒数第 N 个结点(双指针/快慢指针)_赖念安的博客-CSDN博客
参考:【算法-LeetCode】2. 两数相加(双指针/同步指针;链表)_赖念安的博客-CSDN博客