题目链接
https://leetcode.cn/problems/merge-two-sorted-lists/
题目描述
题解
题解1
两个链表本来就是有序的,所以可以使用双指针慢慢遍历两个链表组成的有序序列,和合并两个数组是一样的,我们可以原地合并两个链表
1、我们需要确定以哪个链表为头,当然是以数值小的为头
2、使用双指针分别遍历两个链表,把每一次值最小的点,链接到新链表的后面
3、重复2操作,直到两个指针中某一个指针指向其链表的尾部
4、查看哪个链表没有遍历完,剩下的一定都是最大值,直接拼接到新链表后
注意:影子节点的作用就是用来记录要链表的最后一个节点的,不然没办法拼接
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
// l1和l2有一个为空或者都为空的判断
if (l1 == null || l2 == null) {
return l1 == null ? l2 : l1;
}
// 谁的头小,谁当头
ListNode smallHead = l1.val < l2.val ? l1 : l2;
// 记录头节点用于返回
ListNode head = smallHead;
// 剩下的是大头
ListNode bigHead = smallHead == l1 ? l2 : l1;
// 影子节点,用于添加新节点
ListNode pre = head;
// 小头已经是了,向后移一位
smallHead = smallHead.next;
while (smallHead != null && bigHead != null) {
if (smallHead.val < bigHead.val) {
pre.next = smallHead;
smallHead = smallHead.next;
} else {
pre.next = bigHead;
bigHead = bigHead.next;
}
pre = pre.next;
}
if (smallHead != null)
pre.next = smallHead;
if (bigHead != null)
pre.next = bigHead;
return head;
}
题解2
也可以使用一个新头来链接两个链表,这样就不需要判断谁是大头小头了
题解1是我最近写的代码,题解2是1年前写的代码,果然人是会越来越菜的
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
// 哨兵 -> 指向头节点
ListNode sentinel = new ListNode(-1);
// 临时变量,保存前一个节点,用来比较值
ListNode tempPreNode = sentinel;
// 循环,直到某个链表读完
while (l1 != null && l2 != null) {
// 比较两个链表头节点,小的链接到前一个节点的末尾
if (l1.val <= l2.val) {
tempPreNode.next = l1;
// 临时节点变成刚链上的节点
tempPreNode = l1;
// 指针后移
l1 = l1.next;
} else {
// 和上面一样
tempPreNode.next = l2;
tempPreNode = l2;
l2 = l2.next;
}
}
// 最后至少有一个链表是没有读完的,至少!
// 因为两个链表都是默认有序的,所以找到那个没读完的链表,链到临时节点的尾部就ok
tempPreNode.next = l1 == null ? l2 : l1;
// 根据要求,不需要哨兵节点,所以返回哨兵的下一个节点,也就是合并后的第一个节点
return sentinel.next;
}
题解3
题解3是一种比较装逼的写法,但是思想是一样的,只不过代码看起来比较简洁而已
自己脑补一下递归序就大概明白了,这个思路和题解1是完全一样的
下面是简单的递归序:
1、l1和l2判空,有空直接返回另一个
2、找小头,小头当节点
3、进入递归,小头的节点后移一位
4、重复步骤2和3
5、直到有一个链表被遍历完,把另一个链表没遍历完的接到后面
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
// 归约
if (l1 == null)
return l2;
if (l2 == null)
return l1;
// 递推
// 比较头节点的大小
if (l1.val < l2.val) {
l1.next = mergeTwoLists(l1.next, l2);
return l1;
} else {
l2.next = mergeTwoLists(l1, l2.next);
return l2;
}
}