将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
解法1 暴力解法
思路
最简单的办法就是将所有链表节点先按照升序给排列出来,缓存到数组当中。
然后再去遍历数组,修改每个节点的 next 指针。最后返回数组的第一个节点即可。
代码
function mergeTwoLists(list1: ListNode | null, list2: ListNode | null): ListNode | null {
if (!list1 && !list2) {
return null;
}
const nodeList = [];
let head1 = list1;
let head2 = list2;
while (head1 || head2) {
if (!head1) {
nodeList.push(head2);
head2 = head2.next;
continue;
}
if (!head2) {
nodeList.push(head1);
head1 = head1.next;
continue;
}
if (head1.val <= head2.val) {
nodeList.push(head1);
head1 = head1.next;
} else {
nodeList.push(head2);
head2 = head2.next;
}
}
for (let i = 0; i < nodeList.length; i++) {
nodeList[i].next = i === nodeList.length - 1 ? null : nodeList[i + 1];
}
return nodeList[0];
};
时空复杂度
时间复杂度:O(m + n),两个链表都需要遍历到
空间复杂度:O(m + n)
解法2 虚拟节点
思路
由于要返回新链表的头节点,所以需要先新建一个虚拟头节点。然后在此基础之上去拼接每个节点。
当有剩余链表时,由于链表本身是升序的,所以可以直接拼接。
代码
function mergeTwoLists(list1: ListNode | null, list2: ListNode | null): ListNode | null {
if (!list1 && !list2) {
return null;
}
let dummyHead = new ListNode(-1);
let prev = dummyHead;
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 ? list2 : list1; // 拼接剩下的链表,本身就是升序
return dummyHead.next;
};
时空复杂度
时间复杂度:O(m + n)
空间复杂度:O(1),仅使用常数变量