一、题目描述:
将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 (原题)
示例:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
二、思路及题解
一开始便想到将两个链表遍历保存在数组当中,排序之后再遍历生成新的链表。
法1:
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} l1
* @param {ListNode} l2
* @return {ListNode}
*/
var mergeTwoLists = function(l1, l2) {
if(l1 === null && l2 === null) return null;
const temp = [];
//将链表转换为数组
while(l1 !== null) {
temp.push(l1.val);
l1 = l1.next;
}
while(l2 !== null) {
temp.push(l2.val);
l2 = l2.next;
}
temp.sort((a,b) => a - b);
const head = new ListNode(temp[0]);
let res = head;
for(let i = 1;i < temp.length;i ++) {
res.next = new ListNode(temp[i]);
res = res.next;
}
return head;
};
看了题解之后才发现两个链表均为有序的,其实不必使用数组来进行暂存。遂使用迭代法(
题解链接)重写。概括来说就是创建一个哑节点preNode,通过一次次比较l1,l2元素的大小,使指针永远指向下一个更小的节点,从而保证合并链表的有序性,最后返回preNode的下一个节点即可。
2.法二:迭代法
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} l1
* @param {ListNode} l2
* @return {ListNode}
*/
var mergeTwoLists = function(l1, l2) {
if(l1 === null) { // 若l1为空链表,由于l2已经为有序链表(或为空链表),直接返回即可
return l2;
} else if(l2 === null) { // 同理
return l1;
} else {
const preNode = new ListNode(-1); // 这里实际上设任意数值均可,不一定要设为-1
let temp = preNode; // 设置一个节点来进行迭代
while(l1 !== null || l2 !== null) { // 有一个不为空链表时进行循环
if(l1 === null) { // l1为空链表时只需要遍历l2到新链表即可
temp.next = new ListNode(l2.val);
temp = temp.next;
l2 = l2.next;
} else if(l2 === null) { // 同上
temp.next = new ListNode(l1.val);
temp = temp.next;
l1 = l1.next;
} else {
// 迭代,使得新链表的下一个节点永远指向值较小的节点
if(l1.val <= l2.val) {
temp.next = new ListNode(l1.val);
temp = temp.next;
l1 = l1.next;
} else {
temp.next = new ListNode(l2.val);
temp = temp.next;
l2 = l2.next;
}
}
}
// preNode为哑节点,返回下一个节点
return preNode.next;
}
};