链表
2 两数相加
辅助头节点 + 进位处理
题干:两个链表表示逆序数字,求和后返回新链表。如 (2→4→3) + (5→6→4) = 7→0→8。
- 辅助头节点 pre,最后返回
pre.next - 用
l1 || l2统一循环,空节点取 0
// 简化版:统一循环
var addTwoNumbers = function(l1, l2) {
let p = new ListNode()
let curP = p
let carry = 0
while (l1 || l2) {
let val1 = l1?.val || 0
let val2 = l2?.val || 0
let tempSum = val1 + val2 + carry
carry = 0
if (tempSum > 9) {
carry = 1
tempSum -= 10
}
if (l1) l1 = l1.next
if (l2) l2 = l2.next
curP.next = new ListNode(tempSum)
curP = curP.next
}
if (carry) curP.next = new ListNode(1)
return p.next
}
19 删除链表的倒数第 N 个结点
快慢指针:先拉开 n+1 间距
题干:删除链表的倒数第 n 个节点,返回头节点。
- 头节点可能被删 → 必须构造辅助头节点
- p2 先走 n+1 步,然后 p1/p2 同步走,p2 到头时 p1 刚好在待删节点前一个
var removeNthFromEnd = function(head, n) {
let pre = new ListNode()
pre.next = head
let p1 = pre, p2 = pre
// 拉开 n+1 个间隔
while (n + 1 > 0) { p2 = p2.next; n-- }
while (p2) { p1 = p1.next; p2 = p2.next }
p1.next = p1.next.next // 删除
return pre.next
}
21 合并两个有序链表
辅助头节点 + 逐个比较拼接
var mergeTwoLists = function (list1, list2) {
let pre = new ListNode()
let cur = pre
while (list1 && list2) {
if (list1.val <= list2.val) {
cur.next = list1
list1 = list1.next
} else {
cur.next = list2
list2 = list2.next
}
cur = cur.next
}
// 剩余直接接上
if (list1) cur.next = list1
if (list2) cur.next = list2
return pre.next
}
24 两两交换链表中的节点
三指针 n1/n2/n3 · 画图理解
题干:两两交换相邻节点。1→2→3→4 变 2→1→4→3。
- 坑:交换以后跳两个节点应该是
n1=n2(因为 n2 已经被交换到后面了)
var swapPairs = function(head) {
let n1 = new ListNode()
n1.next = head
let helper = n1
let n2 = n1?.next
let n3 = n2?.next
while (n2 && n3) {
// 交换 n2 和 n3
n2.next = n3.next
n3.next = n2
n1.next = n3
n1 = n2 // 注意:交换后 n2 在后面,跳两个是 n1=n2
n2 = n1.next
n3 = n2?.next
}
return helper.next
}