143. 重排链表
给定一个单链表 L 的头节点 head ,单链表 L 表示为:
L0 → L1 → … → Ln - 1 → Ln 请将其重新排列后变为:
L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …
不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
解:
可以看到前半部分链表是正序,后半部分链表是逆序。所以需要把后半部分链表反转再和前半部分链表依次结合。
- 快慢指针找中点
- 以中点为界限分离两个链表
- 把后面的链表反转
- 慢指针指向前链表,快指针指向后链表。此时快慢指针不再有快慢的含义,只是普通指针。
- 以前-后-前-后的形式合并链表
const reorderList = function(head) {
// 反转链表
const reverseList = (node) => {
let cur = node
let pre = null
while (cur) {
const temp = cur.next
cur.next = pre
pre = cur
cur = temp
}
return pre
}
let quickNode = head
let slowNode = head
// 中点的前一个节点,用于分离前后链表
let pre = null
while (quickNode.next) {
pre = slowNode
slowNode = slowNode.next
quickNode = quickNode.next.next ?? quickNode.next
}
// 避免后续合并链表时循环引用
if (quickNode === slowNode) return head
// 分离链表
pre.next = null
quickNode = reverseList(slowNode)
slowNode = head
let resNode = null
while (slowNode) {
if (!resNode) {
resNode = slowNode
} else {
resNode.next = slowNode
resNode = resNode.next
}
slowNode = slowNode.next
resNode.next = quickNode
quickNode = quickNode.next
resNode = resNode.next
}
return head
};