题目
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
数据范围
两个链表的节点数目范围是 [0, 50]
-100 <= Node.val <= 100
l1 和 l2 均按 非递减顺序 排列
测试用例
示例1

java
输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]
示例2
java
输入:l1 = [], l2 = []
输出:[]
示例3
java
输入:l1 = [], l2 = [0]
输出:[0]
题解1 (迭代,时间O(N+M),空间O1)
java
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
ListNode res=new ListNode(-1);
ListNode pre=res;
while(list1!=null&&list2!=null){
if(list1.val<=list2.val){
pre.next=list1;
list1=list1.next;
}else{
pre.next=list2;
list2=list2.next;
}
pre=pre.next;
}
pre.next=list1 == null? list2:list1;
return res.next;
}
}
题解2(递归,时空O(N+M))
java
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
if(list1==null){
return list2;
}else if(list2==null){
return list1;
}else if(list1.val<=list2.val){
list1.next=mergeTwoLists(list1.next,list2);
return list1;
}else{
list2.next=mergeTwoLists(list1,list2.next);
return list2;
}
}
}
思路
这道题没有特殊要求的话,舅姥姥老老实实用迭代吧,思路清晰,空间复杂度也低,不需要额外说明什么,就是设计了一个指针来记录头,另一个指针来遍历两个list。
递归的话代码较少,但思路麻烦,空间复杂度也高,但最好也掌握一下,万一被问到了呢?他的思路如下:
java
我们可以把这个过程想象成**"层层外包"**的任务。
1. 核心思想:大任务化小任务
我们要合并两个链表,其实只需要做一件事:
比较两个链表的头节点,选出较小的那个作为合并后的头,然后把剩下的部分交给别人去处理。
2. 生活中的例子:排队领书
假设有两队学生(l1 和 l2),每个队都按身高从小到大排列。现在我们要把他们合并成一队。
比较: 你站在门口,看两队排头的人。发现 l1 的排头兵 A 比 l2 的排头兵 B 矮。
决定: 你让 A 站到新队伍的第一位。
外包(递归): 你对 A 说:"剩下的事情我不管了,你去连接后面的人吧。"
递归调用: A 于是回头看了一眼剩下的学生(l1 扣除 A 后的部分,以及完整的 l2 队),重复你刚才的操作。
3. 代码逻辑拆解
让我们对照你提供的 Java 代码来看:
出口(边界情况):
if (l1 == null) return l2; // 如果 l1 没学生了,剩下的全是 l2 的,直接接上去
if (l2 == null) return l1; // 反之亦然
这是递归的"底",没有它程序就会无限循环。
选择与连接:
if (l1.val < l2.val) {
// l1 赢了,l1 成为当前的头
// 关键:l1.next 等于【剩下的 l1】和【完整的 l2】合并的结果
l1.next = mergeTwoLists(l1.next, l2);
return l1; // 返回已经接好的自己
}