自己实现的版本
- 抽出一个模型:用 insertCurrNode 表示不断比较插入的链表,用 checkLeftNode、checkRightNode表示参考链表的左右边界,
- 如果insertCurrNode在[checkLeftNode,checkRightNode] 范围之内直接插入
- 如果insertCurrNode > checkRightNode,则左右边界往右移动;
- 比较过程中不存在 insertCurrNode < checkLeftNode 的情况,因为一开始抽象出的模型中已经比较过两个链表第一个节点大小,以此确认了insertCurrNode的范围;
- 退出边界:insertCurrNode为空;checkRightNode为空的时候,剩余待插入的节点直接拼接到左边,因为链表是已经排序的;
package com.company.linked;
public class Solution9 {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
if (list1 == null) {
return list2;
}
if (list2 == null) {
return list1;
}
//不断比较插入到另外一个链表中的第一个节点
ListNode insertCurrNode;
//作为参考链表的左边界
ListNode checkLeftNode;
if (list1.val >= list2.val) {
checkLeftNode = list2;
insertCurrNode = list1;
} else {
checkLeftNode = list1;
insertCurrNode = list2;
}
ListNode resultHead = checkLeftNode;
//作为参考链表的右边界
ListNode checkRightNode = checkLeftNode.next;
// 如果被参考链表右边界不存在,直接返回结果
if (checkRightNode == null) {
checkLeftNode.next = insertCurrNode;
return resultHead;
}
while (true) {
if (insertCurrNode.val >= checkLeftNode.val && insertCurrNode.val <= checkRightNode.val) {
ListNode removeNode = insertCurrNode;
insertCurrNode = insertCurrNode.next;
checkLeftNode.next = removeNode;
removeNode.next = checkRightNode;
checkLeftNode = checkLeftNode.next;
} else {
checkLeftNode = checkLeftNode.next;
checkRightNode = checkRightNode.next;
}
//如果不断比较插入的节点为空,直接返回
if (insertCurrNode == null) {
break;
}
//如果参考的右边界为空,直接剩余比较链表节点拼接到左边界后面,因为两个链表都是有序的,可以这样拼接
if (checkRightNode == null) {
checkLeftNode.next = insertCurrNode;
break;
}
}
return resultHead;
}
}
迭代版本:
- 有点像插入排序,比较两个链表中较小的当前节点拼接到合并后链表的末尾
- 也有点像归并排序,将两个有序的列表合并成最终有序
- 这方法才是本地的考点
package com.company.linked;
public class Solution9_2 {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode prehead = new ListNode(-1);
ListNode prev = prehead;
while (l1 != null && l2 != null) {
if (l1.val <= l2.val) {
prev.next = l1;
l1 = l1.next;
} else {
prev.next = l2;
l2 = l2.next;
}
prev = prev.next;
}
// 合并后 l1 和 l2 最多只有一个还未被合并完,我们直接将链表末尾指向未合并完的链表即可
prev.next = l1 == null ? l2 : l1;
return prehead.next;
}
}