题目:给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
用图表示的话,类似这样
首先我们来看循环迭代的解决方法
- 我们生成一个辅助节点叫
dummy node
链接在头节点之前,为什么要链接在头节点之前呢?为了不影响后面头节点与相邻节点交换,更用于方便最后输出整个交换过的链表,如下图
- 随后我们还需要定义3个变量,
prev
代表前置节点,n1
代表当前节点,n2
代表与n1
相邻的节点
- 申请完变量后,首先将前置节点指向
n2
,因为交换完成后n2
将是第一个节点
prev.next = n2
复制代码
- 将
n1
节点指向n2
的后一个节点,第一次情况下也就是[3,4]
n1.next = n2.next
复制代码
- 然后第一次交换相邻节点,将
n2
节点指向n1
节点
n2.next = n1
复制代码
- 第一次交换完成后,链表结构变成[-1, 2, 1, 3, 4]这样
- 在迭代的最后,将前置节点
prev
改变为n1
,并将当前节点head
改变为n1.next
,为第二次迭代做准备
prev = n1;
head = n1.next;
复制代码
-
在我们进入下一次迭代前,我们设置迭代条件为有当前节点和当前的下一个节点时才进行交换,这也是符合题目要求的
-
最后我们输出辅助节点
dummy.next
作为交换完的节点,这是因为prev
节点在迭代过程中已经被移动了
完整代码如下
var swapPairs = function(head) {
// build a dummy nodes link to head, like [-1,1,2,3,4]
let dummy = new ListNode(-1)
dummy.next = head
// assign dummy to prev because prev will change to forward nodes, but dummy always link to first node, in this example is link to [2...]
let prev = dummy
// loop when head and head.next is not null
while(head && head.next) {
// cur node
let n1 = head
// next node
let n2 = head.next
// link to next node, first time is [2...]
prev.next = n2
// swap
n1.next = n2.next
n2.next = n1
// make prev move to forward node for next loop use, for example, first time prev assign to n1, when next loop prev.next like n1.next [1,3,4]
prev = n1
// change head is n1.next
head = n1.next
}
return dummy.next
};
复制代码
时间复杂度为O(N),空间复杂度为O(1)
然后我们再来用递归实现一下
- 首先设置递归终止条件,当没有当前节点或没有下一个节点时,递归结束
if(!head || !head.next) return head
复制代码
- 然后,我们申请3个变量,
v1
为当前节点,v2
为下一个节点,v3
为第三个节点
let v1 = head ;
let v2 = v1.next;
let v3 = v2.next;
复制代码
- 我们交换
v1
和v2
,继续递归v3
并赋给v1
- 在函数的最后,我们返回
v2
, 因为无论是那次递归,v2
都将代表本次交换中的第一个节点
完整代码
var swapPairs = function(head){
// stop
if(!head || !head.next) return head
// do
let v1 = head
let v2 = v1.next
let v3 = v2.next
v2.next = v1
// recursion
v1.next = swapPairs(v3)
return v2
}
复制代码
参考
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END