leetcode 21题
注意的点
- 插入位置可能是链表的末尾,则node.next是null,可能触发空指针。
- 给出的数据中,两个链表都有可能是空的。注意考虑特殊情况。
我的版本
有根据数组创建单链表的代码,也有打印单链表的代码。
核心思想:遍历要插入的单链表,所有元素都插入为止。一层循环负责遍历新插入的链表,里面的循环负责寻找要插入到原链表的位置。
public class TestLeetcode21 {
static class ListNode {
int val;
ListNode next;
ListNode(int val) {
this.val = val;
}
}
public static void main(String[] args) {
// int[] list1 = {1, 2, 4};
// int[] list2 = {1, 3, 4};
// ListNode head = mergeTwoLists(createList(list1), createList(list2));
// printList(head);
//
// int[] list3 = {};
// int[] list4 = {0};
// ListNode head2 = mergeTwoLists(createList(list3), createList(list4));
// printList(head2);
int[] list5 = {2};
int[] list6 = {1};
ListNode head3 = mergeTwoLists(createList(list5), createList(list6));
printList(head3);
}
public static ListNode createList(int[] nums) {
if (nums != null && nums.length == 0) {
return null;
}
ListNode head = new ListNode(nums[0]);
ListNode cur = head;
for (int i = 1; i < nums.length; i++) {
cur.next = new ListNode(nums[i]);
cur = cur.next;
}
printList(head);
return head;
}
public static void printList(ListNode head) {
while (head != null) {
System.out.print(head.val);
if (head.next != null) {
System.out.print("->");
}else{
System.out.print("->null");
}
head = head.next;
}
System.out.println();
}
public static ListNode mergeTwoLists(ListNode list1, ListNode list2) {
if (list1 == null) {
return list2;
} else {
if (list2 == null) {
return list1;
}
}
//确定谁是等待插入的单链表
ListNode waitForHead;
ListNode newInsertHead;
if (list1.val <= list2.val) {
waitForHead = list1;
newInsertHead = list2;
} else {
waitForHead = list2;
newInsertHead = list1;
}
ListNode readNewInsert = newInsertHead;
ListNode readWait = waitForHead;
while (readNewInsert != null) {
//寻找插入的位置
while (!(
readNewInsert.val >= readWait.val &&
((readWait.next==null)||
(readWait.next!=null&&readNewInsert.val <= readWait.next.val))
)) {
readWait = readWait.next;
}
//插入
ListNode tempHead = readNewInsert.next;
readNewInsert.next = readWait.next;
readWait.next = readNewInsert;
readNewInsert = tempHead;
}
return waitForHead;
}
}
官方版本
核心思想:新生成一个-1节点,一重循环同时遍历两个链表,谁的节点小,就指向谁。
优点:代码简洁,思路清晰。
class Solution {
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;
}
}