链表
问:
- 如何判断是否为回文链表
- 给定一个链表的head,和一个指定值target,将单向链表按target调整为左边都是小于target,中间等于target、右边大于target的顺序
- 一个链表中,每个节点都有一个rand指针,这个指针指向链表内任一节点或者null,如何完全复制这个链表
解:
- 快慢指针解法,快指针走两个位置,慢指针走一个位置,当快指针走完,慢指针就在中点,知道中点位置就可以比较了。
function isPalindrome(head) {
let slowIdx = head
let quickIdx = head
let midIdx = null
while (quickIdx.next) {
slowIdx = slowIdx.next
quickIdx = quickIdx.next.next ?? quickIdx.next
}
midIdx = slowIdx
slowIdx = head
// 反转后半部链表,reverseList方法自行实现
const tempNode = reverseList(midIdx)
while (slowIdx !== midIdx) {
if (slowIdx === quickIdx) {
slowIdx = slowIdx.next
quickIdx = quickIdx.next
} else {
reverseList(tempNode)
return false
}
}
reverseList(tempNode)
return true
}
2.划分为三个链,最后把小于链、等于链、大于链连接起来(如果存在的话)
function divisionArea(head, target) {
let smStart = null
let smEnd = null
let eqStart = null
let eqEnd = null
let lgStart = null
let lgEnd = null
let curNode = head
while (curNode) {
if (curNode.value < target) {
smStart = smStart ?? curNode
if (smEnd) smEnd.next = curNode
smEnd = curNode
}
if (curNode.value === target) {
eqStart = eqStart ?? curNode
if (eqEnd) eqEnd.next = curNode
eqEnd = curNode
}
if (curNode.value > target) {
lgStart = lgStart ?? curNode
if (lgEnd) lgEnd.next = curNode
lgEnd = curNode
}
curNode = curNode.next
}
lgEnd && (lgEnd.next = null)
smEnd && (smEnd.next = eqStart ?? lgStart)
eqEnd && (eqEnd.next = lgStart)
return smStart ?? eqStart ?? lgStart
}
3.在原链表上按顺序复制一份,这样复制rand属性时,就可以根据原节点的rand找到复制节点应该对应的rand节点,然后拆分链表即可
// 1 - 2 - 3
function copyLinkedList(head) {
let current = head
let res = null
// 复制next属性
while (current) {
// 复制节点
const copyNode = new Node(current.value)
// 将复制的节点,放到正常节点后面
const temp = current.next
current.next = copyNode
copyNode.next = temp
current = temp
}
current = head
// 最终为 1 - 1' - 2 - 2' - 3 - 3'
// 复制rand属性
while (current) {
const copyNode = current.next
// 譬如当前节点是1,复制节点是1'。 1的rand指向3,那么1'的rand指向3的next(因为3和3'是有序的)
copyNode.rand = current.rand.next
current = current.next.next
}
current = head
// 分离链表
while (current) {
const temp = current.next
res ??= temp
current.next = current.next.next
current = temp
}
return res
}