题目
输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。
示例1:
输入:1->2->4, 1->3->4 输出:1->1->2->3->4->4 限制:
0 <= 链表长度 <= 1000
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/he… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
插入排序
构造哨兵节点 sentinel,sentinel.next = head1。遍历链表 head2 在链表 dummy 中寻找合适的插入位置。特别注意遍历完整个链表 dummy,发生空指针的情况, 返回 dummy.next。
双指针
题目描述两个链表时递增排序,你可以使用双指针 p q 遍历两个链表判定新链表的下一元素。算法流程如下:
-
初始化哨兵节点 dummy,dummy.next = head1;节点 curr 指向 dummy。
-
循环合并。当 p q 任意一个为空跳出循环,判定 p q 的 value 大小决定后继节点。
- 当 p.val < q.val 时,p 是下一后继节点, curr.next = p;
- 当 q.val ≥ q.val 时,q 是下一后继节点,curr.next = q;
curr 前进一位,curr = curr.next; 循环往复执行。
-
合并剩余尾部链表。当 p 或 q 任意一个为空时,跳出第2步循环合并。
判定 p == null 是否成立,将剩余尾部合并到 curr 节点。
代码实现
插入排序
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null || l2 == null) return l1 != null ? l1 : l2;
ListNode dummy = new ListNode(0); dummy.next = l1;
ListNode p = l2; ListNode lastSorted = dummy;
while (p != null) {
ListNode pred = lastSorted;
while (pred.next != null && pred.next.val <= p.val) {
pred = pred.next;
}
ListNode t = p.next;
p.next = pred.next;
pred.next = p;
lastSorted = p;
p = t;
}
return dummy.next;
}
需要遍历两个链表时间复杂度是O(M+N) 其中M和N是链表的长度。采用原地排序算法空间复杂度是O(1)。
双指针
public ListNode twoPointer(ListNode l1, ListNode l2) {
ListNode dummy = new ListNode(); dummy.next = l1;
ListNode p = l1, q = l2, curr = dummy;
while (p != null && q != null) {
if (p.val < q.val) {
curr.next = p;
p = p.next;
} else {
curr.next = q;
q = q.next;
}
curr = curr.next;
}
curr.next = (p != null ? p : q);
return dummy.next;
}
需要遍历两个链表时间复杂度是O(M+N) 其中M和N是链表的长度。声明了 dummy, p, q, curr 变量,采用原地算法空间复杂度是O(1)。
知识点
链表的插入节点操作。
双指针和插入排序思想