携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第17天,点击查看活动详情
LeedCode 1721:交换链表中的节点
题目描述
给你链表的头节点 head 和一个整数 k 。
交换 链表正数第 k 个节点和倒数第 k 个节点的值后,返回链表的头节点(链表 从 1 开始索引)。
解题思路
思路一:利用快慢指针
可以先参考LeetCode 19:删除链表的倒数第 N 个结点 - 掘金 (juejin.cn)
1. 根据快慢指针,定位到第k个节点的前一个节点kNodePre;倒数第 k 个节点slow;倒数第 k 个节点前一个节点lastKNodePre
- 分三种情况:
- 两节点是同一个;不需要交换,直接返回;如head = [1,2,3,4,5], k = 3
- 两节点相邻;
- 两节点不相邻;
我们使用dummy节点, kNodePre指正数第 k 个节点前一个节点,即第 k - 1个节点
for (let i = 1; i < k; i++) {
kNodePre = fast;
fast = fast.next;
}
当fast指针走到头时, slow指向倒数第 k 个节点,lastKNodePre指倒数第 k 个节点前一个节点
while (fast !== null && fast.next !== null) {
lastKNodePre = slow;
slow = slow.next;
fast = fast.next;
}
两个节点相邻, 交换代码如下:
if (kNode.next === slow) {
// 两个节点相邻; 如 head = [1,2], k = 1
kNode.next = slow.next;
slow.next = kNode;
kNodePre.next = slow;
}
完整实现代码如下:
/**
* @param {ListNode} head
* @param {number} k
* @return {ListNode}
*/
var swapNodes = function (head, k) {
if (head === null || head.next === null) {
return head;
}
let dummy = new ListNode(0, head);
let kNodePre = dummy,
lastKNodePre = dummy,
slow = head,
fast = head;
// kNodePre指正数第 k 个节点前一个节点,即第 k - 1个节点
for (let i = 1; i < k; i++) {
kNodePre = fast;
fast = fast.next;
}
// kNode指正数第 k 个节点
var kNode = fast;
// fast指针走到头时, slow指向倒数第 k 个节点
// lastKNodePre指倒数第 k 个节点前一个节点
while (fast !== null && fast.next !== null) {
lastKNodePre = slow;
slow = slow.next;
fast = fast.next;
}
// 正数第 k 个节点 与 倒数第 k 个节点 是同一个时, 不用交换,直接返回; 如 head = [1,2,3,4,5], k = 3
if (kNode === slow) {
return dummy.next;
} else if (kNode.next === slow) {
// 两个节点相邻; 如 head = [1,2], k = 1
kNode.next = slow.next;
slow.next = kNode;
kNodePre.next = slow;
} else if (slow.next === kNode) {
// 两个节点相邻; 如 head = [1,2], k = 2
slow.next = kNode.next;
kNode.next = slow;
lastKNodePre.next = kNode;
} else {
var tmp = slow.next;
kNodePre.next = slow;
lastKNodePre.next = kNode;
slow.next = kNode.next;
kNode.next = tmp;
}
return dummy.next;
};
简化版:
var swapNodes = function (head, k) {
if (head === null || head.next === null) {
return head;
}
var dummy = new ListNode(0, head);
var kNodePre = dummy,
kNode,
lastKNode;
// kNodePre指正数第 k 个节点前一个节点,即第 k - 1个节点
for (var i = 1; i < k; i++) {
kNodePre=kNodePre.next;
}
var slow = dummy,
fast = kNodePre.next;
// 此时slow指向倒数第 k-1 个节点
while (fast.next != null) {
fast = fast.next;
slow = slow.next;
}
if (kNodePre != slow) {
// kNode指正数第 k 个节点
kNode = kNodePre.next;
// lastKNode指向倒数第 k 个节点
lastKNode = slow.next;
slow.next = kNode;
kNodePre.next = lastKNode;
var tmp = lastKNode.next;
lastKNode.next = kNode.next;
kNode.next = tmp;
}
return dummy.next;
};