作者 | 小夕
出品 | 公众号:小夕学算法
题目
输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。
示例1:
输入:1->2->4, 1->3->4 输出:1->1->2->3->4->4 限制:
0 <= 链表长度 <= 1000
注意:本题与主站 21 题相同:https://leetcode-cn.com/problems/merge-two-sorted-lists/
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/he-bing-liang-ge-pai-xu-de-lian-biao-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
![21136a35b9a0c3e39eee87d375c5f3bb.png](https://i-blog.csdnimg.cn/blog_migrate/049aac25f39e2464632252b972cfb4e0.png)
文字思路
设置dummy为哑结点,放置于新链表之前,最后返回的就是dummy.next;设置cur为当前节点,从dummy开始
当两个链表都非空时进入循环,令新链表的下一个节点cur.next为val更小的节点,相应的链表节点后移一位
每次循环记得cur也要后移一位
如果循环结束后还有链表非空,cur指向非空链表
返回dummy.next
图解思路
![3512031dfe717d75e26ef63f74e10d01.png](https://i-blog.csdnimg.cn/blog_migrate/798cc10be3a83c3744e83b7b4ea1c060.png)
![62c8c44ee484680a63abde6d2931ec75.png](https://i-blog.csdnimg.cn/blog_migrate/a41111f7c83cda6e59c74628bf867b7b.png)
![1bdae6168ae72b37890d7c2015368ceb.png](https://i-blog.csdnimg.cn/blog_migrate/1a61d4f8ef0796692d45f6156ba4ae1a.png)
![88cb55561b917526ac3f6debd9d03855.png](https://i-blog.csdnimg.cn/blog_migrate/d94b912e2045470b6adf268ab5024940.png)
![5900d2301a5daa87aa624d233fc0cb06.png](https://i-blog.csdnimg.cn/blog_migrate/718a08a994ebc6f0bdc5db392989c947.png)
![a96df90bc1779e90e10c65b5a05cadba.png](https://i-blog.csdnimg.cn/blog_migrate/7ff579d6cbd644ab54149e9169492b64.png)
![75b4f7ec0d811b1e568ead87bca59de2.png](https://i-blog.csdnimg.cn/blog_migrate/5fb0ea8d828ee6092ade77dc227c5bf9.png)
![cb2009d6cfddba55a43f0ac39623f9ba.png](https://i-blog.csdnimg.cn/blog_migrate/3860ea209b695e6106f477de95e0faf6.png)
![22798932ef7a228f813c96f77b37e8ee.png](https://i-blog.csdnimg.cn/blog_migrate/0da48c8823447ed7e4d6a4367d93633a.png)
![23db978820d4be2abc346e3c604e0c74.png](https://i-blog.csdnimg.cn/blog_migrate/507041d1b063b6489cd45c2bfd462453.png)
![6c3461b05a0c861de7989829556d9964.png](https://i-blog.csdnimg.cn/blog_migrate/20cb203f9540985e86556e1313fa1ab5.png)
![35ec1b42a83d0a857d2473f84c5542c7.png](https://i-blog.csdnimg.cn/blog_migrate/fc194ef18504ba71a454f052da3e56c2.png)
![83b18d6eed6c3f520636b559edb5d712.png](https://i-blog.csdnimg.cn/blog_migrate/8bf1b535d7d39b04745fc1df482c9fa7.png)
![3109b52d111a6d5131ece79a345cf30b.png](https://i-blog.csdnimg.cn/blog_migrate/ea144626b99fa6fbd8fc518ad44db14d.png)
![346ec2936ab2cc3dfd2e8d6b1af2a2ee.png](https://i-blog.csdnimg.cn/blog_migrate/7fdf402dca71dea9f2918b899af46d8d.png)
![2250c86e6788a2a70e5d23a6167e55ad.png](https://i-blog.csdnimg.cn/blog_migrate/4e67c8fd3e89c31f72d6d80a15da9885.png)
![9d203d40129cdf28bfc0f378f26b12df.png](https://i-blog.csdnimg.cn/blog_migrate/90e588c8405fb6f46cb11933d936183f.png)
上述图片中的文字:
创建一个伪头结点 tempHead 节点 cur 指向 tempHead 节点 接下来比较 head1 和 head2 两个链表 哪个节点小 就把 tempHead 指向谁
head1.val >= head2.val 所以 head2 节点是值较小的,让cur.next指向head2节点
cur.next指向了head2,如图所示,接着让head2 = head2.next,让head2 继续参与接下来的比较。
完成了cur.next 指向了head2,head2 = head2.next,接下来让 cur指向下一个节点 cur = cur.next
完成了cur.next指向了head2,head2 = head2.next,cur = cur.next变成了如图所示。
接着继续重复上述过程 继续比较 head1.val < head2.val
由于 head1.val < head2.val 继续执行之前的三步:cur.next = head1 head1 = head1.next cur = cur.next
由于 head1.val < head2.val 继续执行之前的三步:cur.next = head1 head1 = head1.next cur = cur.next 执行完这三步以后,如图所示。
接下来继续比较head1.val和head2.val 因为 head1.val < head2.val 继续执行之前的三步:cur.next = head1 head1 = head1.next cur = cur.next
cur.next = head1 head1 = head1.next cur = cur.next如图所示
接下来继续比较head1.val和 head2.val 因为 head1.val > head2.val:所以执行 cur.next = head2 head2 = head2.next cur = cur.next
接下来继续比较head1.val和 head2.val 因为 head1.val >= head2.val:所以继续执行 cur.next = head2 head2 = head2.next cur = cur.next
执行完如图所示,head1指向了null,所以排序列表一遍历结束了,所以把排序列表二接到合并排序列表后面。
接到后面,cur.next = head2 完成全部排序。
由于需要返回1-1-2-3-4-4 所以最后返回tempHead.next 节点
动画
![5a463cb591c6b3196f4bc9c5a5b3b1dc.gif](https://i-blog.csdnimg.cn/blog_migrate/1e0f1f57bade4739018917a3ab2c5cec.gif)
代码
Java
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode dummy = new ListNode();
ListNode cur = dummy;
while(l1 != null && l2 != null){
if(l1.val <= l2.val){
cur.next = l1;
l1 = l1.next;
}else{
cur.next = l2;
l2 = l2.next;
}
cur = cur.next;
}
cur.next = l1 != null ? l1 : l2;
return dummy.next;
}
}
JS
const mergeTwoLists = (l1, l2) => {
// 定义一个虚拟节点,最后返回虚拟节点的下一个节点
const res = new ListNode(0);
// 定义p指向虚拟节点
let p = res;
// 定义p1,p2分别指向两个链表头部
let [p1, p2] = [l1, l2];
// 当p1, p2都有值的时候
while (p1 && p2) {
// 如果p1指向的值小,则p指向p1的值
// p1右移
// 否则p指向p2的值,p2右移
if (p1.val < p2.val) {
p.next = p1;
p1 = p1.next;
} else {
p.next = p2;
p2 = p2.next;
}
// 记得p也要右移
p = p.next;
}
// 到最后退出循环了,p1,p2肯定有且只有一个是null
// 那么另一个不是null的还没有连接到p上
// 把p再连接到不是null的那个
p.next = p1 ? p1 : p2;
// 返回虚拟节点的下一个节点
return res.next;
};
Python
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
res = ListNode(-1)
p = res
while l1 and l2:
if l1.val < l2.val:
p.next = l1
l1 = l1.next
else:
p.next = l2
l2 = l2.next
p = p.next
p.next = l1 if l1 is not None else l2
return res.next
C++
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* pHead = new ListNode(0);
ListNode* pNode = pHead;
while (l1 != NULL && l2 != NULL) {
if (l1->val < l2->val) {
pNode->next = l1;
l1 = l1->next;
}
else {
pNode->next = l2;
l2 = l2->next;
}
pNode = pNode->next;
}
// 比较妙的一点在这里,就像归并排序一样最后要把没合并完的直接放进来,这里就不用遍历了,直接把节点挂上来就行
if (l1)
pNode->next = l1;
else if (l2)
pNode->next = l2;
return pHead->next;
}
};
Go
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
if l1==nil {return l2}
if l2==nil {return l1}
var n *ListNode
if l1.Val<l2.Val {
n = l1
n.Next = mergeTwoLists(l1.Next,l2)
} else {
n = l2
n.Next = mergeTwoLists(l1,l2.Next)
}
return n
}
![860efb16e819ab294a41f21d7cd81324.png](https://i-blog.csdnimg.cn/blog_migrate/dd7fb87a6a34017fcfd637ff373025e1.png)
![3ac5d0472959ee4df9e4d3e6121127ce.png](https://i-blog.csdnimg.cn/blog_migrate/8e833bb39bc8c6ed939b43e8d3d66cc6.png)
本文原创作者:小夕,一名BAT大厂程序媛。
文章首发平台:微信公众号【小夕学算法】。
如果喜欢小夕的文章,请点个关注,分享给更多的人,小夕将持续更新,谢谢啦!
关注下方公众号,分享硬核知识
关注上方公众号,回复 算法 获取大厂面试宝典
▼
往期精彩回顾
▼