24. 两两交换链表中的节点
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例:
给定 1->2->3->4, 你应该返回 2->1->4->3.
递归
思路:
- 返回值:交换完成的子链表
- 调用单元:设需要交换的两个点为 head 和 next,head 连接后面交换完成的子链表,next 连接 head,完成交换
- 终止条件:head 为空指针或者 next 为空指针,也就是当前无节点或者只有一个节点,无法进行交换
- 重要的是 找到递归单元 设置递归出口 返回调用自身的递归函数
结果: 64ms 还可以啦 时间复杂度是O (nlonn)级别的 但毕竟用了递归
/**
* 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
let next = head.next
head.next = swapPairs(next.next)
next.next = head
return next
};
迭代
思路: 我们把链表分为两部分,即奇数节点为一部分,偶数节点为一部分,A 指的是交换节点中的前面的节点,B 指的是要交换节点中的后面的节点。在完成它们的交换,我们还得用 prevNode 记录 A 的前驱节点。
结果: 64ms 时间复杂度O(n)级别
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var swapPairs = function(head) {
let dummyNode = new ListNode(-1)
dummyNode.next = head
let pre = dummyNode
while(head !== null && head.next !== null) {
// 奇数节点
let first_node = head
// 偶数节点
let seconde_node = head.next
// pre 指向 偶数节点
pre.next = seconde_node
//修改奇数节点 偶数节点的指向
first_node.next = seconde_node.next
seconde_node.next = first_node
// 类似于i++ j++ 这么理解
pre = first_node
head = head.next
}
// dummyNode的下一个节点 就是我们所需的链表
return dummyNode.next
}
// 优化了一下
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var swapPairs = function(head) {
// 设置递归的出口
let dummyNode = new ListNode()
dummyNode.next = head
let pre = dummyNode
while(head !== null && head.next !== null) {
let firstNode = head
let secondNode = head.next
pre.next = secondNode
firstNode.next = secondNode.next
secondNode.next = firstNode
pre = head
head = head.next
}
return dummyNode.next
};
// 这道题真的卡了半天 弄不清楚递归的最小重复单元 花了一点时间弄懂了 感觉对链表的理解更深层次了一些