链表问题,一般同时可以用递归和迭代解决,递归和迭代“在每一轮中要做的事”是一样的,只是写法上的区别。所以有必要在草稿纸上确认“每一轮到底应该做什么”。
经常使用的技巧有:
- 设置虚拟头结点,从而统一对所有结点的操作
- 使用 pre、cur指针,并保存 temp = cur.next,完成改变指向的操作时,修改pre和cur的指向,常见于迭代法。在递归法中,函数可以接受pre和cur两个参数,只需要把下一轮的指针传入即可。
21. 合并两个有序链表
/**
* @param {ListNode} list1
* @param {ListNode} list2
* @return {ListNode}
*/
var mergeTwoLists = function (list1, list2) {
if (!list1) return list2;
if (!list2) return list1;
if (list1.val < list2.val) {
list1.next = mergeTwoLists(list1.next, list2);
return list1;
} else {
list2.next = mergeTwoLists(list1, list2.next);
return list2;
}
};
var mergeTwoLists = function (list1, list2) {
const preHead = new ListNode();
let prev = preHead;
while (list1 && list2) {
if (list1.val < list2.val) {
prev.next = list1;
list1 = list1.next;
} else {
prev.next = list2;
list2 = list2.next;
}
prev = prev.next;
}
prev.next = list1 ? list1 : list2;
return preHead.next;
};
206. 反转链表
// 递归
var reverseList = function (head) {
return reverse(null, head);
};
function reverse(pre, cur) {
if (!cur) return pre;
const temp = cur.next;
cur.next = pre;
return reverse(cur, temp);
}
// 迭代
var reverseList = function (head) {
let pre = null;
let cur = head;
while (cur) {
const temp = cur.next;
cur.next = pre;
pre = cur;
cur = temp;
}
return pre;
};
24. 两两交换链表中的结点
/**
* @param {ListNode} head
* @return {ListNode}
*/
// 迭代
var swapPairs = function (head) {
if (!head) return null;
const dummyHead = new ListNode(0, head);
let pre = dummyHead;
let cur = head;
let after = head.next;
while (pre && cur && after) {
const temp = after.next;
pre.next = after;
after.next = cur;
cur.next = temp;
pre = cur;
cur = pre?.next;
after = cur?.next;
}
return dummyHead.next;
};
// 递归,和迭代基本上是一样的逻辑,写法不同罢了
var swapPairs = function (head) {
if (!head) return null;
const dummyHead = new ListNode(0, head);
let pre = dummyHead;
let cur = head;
let after = head.next;
swap(pre, cur, after);
return dummyHead.next;
};
function swap(pre, cur, after) {
if (!pre || !cur || !after) return;
const temp = after.next;
pre.next = after;
after.next = cur;
cur.next = temp;
pre = cur;
cur = pre?.next;
after = cur?.next;
swap(pre, cur, after);
}