LeetCode系列记录我学习算法的过程。
持续创作,加速成长!这是我参与「掘金日新计划 6 月更文挑战」的第 20 天,点击查看活动详情
题目
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:
输入: l1 = [1,2,4], l2 = [1,3,4]
输出: [1,1,2,3,4,4]
提示
- 两个链表的节点数目范围是
[0, 50] -100 <= Node.val <= 100l1和l2均按 非递减顺序 排列
思路
给定的两个链表均是升序的,那解起来其实就很简单了
- 如果两个链表有为空的,直接返回不为空的链表即可
- 定义头尾两个指针,判断两个链表头结点大小,然后初始化头尾指针为较小项的结点
- 遍历两个链表,结束条件为其中一个链表遍历完
- 判断两个链表当前结点大小,将尾指针指向较小项,并移动较小项链表
- 将尾指针指向下一项,然后将下一项置空
- 最后将尾指针指向未遍历完的链表
- 返回头指针
代码实现
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} list1
* @param {ListNode} list2
* @return {ListNode}
*/
var mergeTwoLists = function(list1, list2) {
// 如果两个链表有为空的,则直接返回不为空的链表即可
if(!list1 || !list2) return list1 || list2
// 头指针和尾指针
let head = null, next = null
// 判断 list1 和 list2 头结点的大小,初始化头尾指针
if(list1.val < list2.val) {
head = next = list1
list1 = list1.next
} else {
head = next = list2
list2 = list2.next
}
// 当两个链表遍历完某一个时结束循环
while(list1 && list2) {
// 将尾指针指向较小的一项,并移动较小项的指针
if(list1.val < list2.val) {
next.next = list1
list1 = list1.next
} else {
next.next = list2
list2 = list2.next
}
// 将尾指针指向下一项
next = next.next
// 将尾指针下一项置空
next.next = null
}
// 将尾指针下一项指向未遍历完的链表
next.next = (list1 || list2)
// 返回头指针
return head
};
优化
没想到还可以用递归的方式来实现,而且代码简洁了很多
既然 mergeTwoLists 这个方法是将两个链表进行升序合并,那我们就可以先找下较小项的链表
然后将该链表的下一项设置为 mergeTwoLists 该链表后续及另一链表的结果
/**
* @param {ListNode} list1
* @param {ListNode} list2
* @return {ListNode}
*/
var mergeTwoLists = function(list1, list2) {
// 如果有链表为空 返回不为空的链表
if (!list1 || !list2) return list1 || list2
if (list1.val < list2.val) {
// 递归实现链表合并
list1.next = mergeTwoLists(list1.next, list2)
return list1
} else {
list2.next = mergeTwoLists(list2.next, list1)
return list2
}
};