将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

解题思路

递归

image.png

  1. public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
  2. if (l1==null)
  3. return l2;
  4. if (l2==null)
  5. return l1;
  6. if(l1.val<l2.val) {
  7. l1.next = mergeTwoLists(l1.next, l2);
  8. return l1;
  9. }else{
  10. l2.next = mergeTwoLists(l1,l2.next);
  11. return l2;
  12. }
  13. }

复杂度分析

时间复杂度:O(n + m)。 因为每次调用递归都会去掉 l1 或者 l2 的头元素(直到至少有一个链表为空),函数 mergeTwoList 中只会遍历每个元素一次。所以,时间复杂度与合并后的链表长度为线性关系。

空间复杂度:O(n + m)。调用 mergeTwoLists 退出时 l1 和 l2 中每个元素都一定已经被遍历过了,所以 n+m 个栈帧会消耗 O(n + m)的空间。

迭代

image.png

  1. public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
  2. //虚拟头结点
  3. ListNode preHead = new ListNode(-1);
  4. ListNode prev = preHead;
  5. while(l1!=null&&l2!=null){
  6. if(l1.val<l2.val){
  7. prev.next=l1;
  8. l1=l1.next;
  9. }else{
  10. prev.next=l2;
  11. l2=l2.next;
  12. }
  13. prev=prev.next;
  14. }
  15. prev.next = l1 == null ? l2 : l1;
  16. return preHead.next;
  17. }

复杂度分析

时间复杂度:O(n + m) 。因为每次循环迭代中,l1 和 l2 只有一个元素会被放进合并链表中, while 循环的次数等于两个链表的总长度。所有其他工作都是常数级别的,所以总的时间复杂度是线性的。

空间复杂度:O(1)) 。迭代的过程只会产生几个指针,所以它所需要的空间是常数级别的。