24、两两交换链表中的节点
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
先看清题目,是两两交换链表中的节点,不是交换节点的值,并且是原地交换
理解完题目的意思,可以看出这是两两分组进行交换,那么只需要找出每次交换的规律即可
与反转链表相似,这里可以利用虚拟头节点来便于操作
我们知道交换两个节点的步骤,假设虚拟头结点为dummy,交换node1和node2节点(节点位置如下:虚拟头结点=》node1=》node2)
交换过程
1、node1.next = node2.next(断开1,2连接,node1指向node2后面元素 )
2、dummy.next = node2 (连接虚拟头结点和node2)
3、node2.next = node (连接node2和node1)
通过这三步,完成node1和node2的节点交换
但这只是一对节点交换,而这里是对整个链表两两交换,因此需要确定下次虚拟节点位置,通过分析,可以确定下次虚拟节点为这次交换后node1的位置
dummy = node1
下次交换时的node1,node2也是同样的dummy.next 和dummy.next.next
循环上述过程便完成了两两交换的过程
最后需要确定循环终止条件:dummy.next和dummy.next.next 都同时存在
两个难点:
1、确定交换过程,利用虚拟头结点
2、确定循环终止条件
解决这两个问题,代码就显而易见了
var swapPairs = function (head) {
let dummy = new ListNode(0, head); // 创建虚拟头节点
let current = dummy;
while (current.next !== null && current.next.next !== null) {
let first = current.next; // 第一节点
let second = current.next.next; // 第二节点
// 交换节点
first.next = second.next;
second.next = first;
current.next = second;
// 移动到下一对节点
current = first;
}
return dummy.next;
};

19.删除链表的倒数第 N 个结点
给你一个链表,删除链表的倒数第 n
个结点,并且返回链表的头结点。
当需要返回头结点的时候,利用虚拟头结点进行返回
这里灵活使用快慢指针,求倒数第几个就让快指针提前跑几格
再让快慢指针一起跑,直到快指针到达链表末尾
删除操作:slow.next = slow.next.next
完整代码
var removeNthFromEnd = function (head, n) {
// 创建虚拟头节点以简化删除头节点的处理
let dummy = new ListNode(0, head);
let fast = dummy, slow = dummy;
// 快指针先移动 n 步
for (let i = 0; i < n; i++) {
fast = fast.next;
}
// 快慢指针同时移动,直到快指针到达链表末尾
while (fast.next !== null) {
fast = fast.next;
slow = slow.next;
}
// 删除目标节点
slow.next = slow.next.next;
// 返回链表的新头节点
return dummy.next;
};