21. 合并两个有序链表

1、题目描述:

21. 合并两个有序链表_第1张图片

2、 解决方案

题目分析:

  • 两个目标链表,是两个【升序链表】,也就是说这两个链表自身都是【已经排好序】的

前提:链表的结构体

class ListNode{
   int val;
   ListNode next;
   ListNode(int val){
      this.val = val;
   }
}

2-1、迭代思路:

在两个已经排好序的链表中,进行合并,其实就是两个元素比较,较小的元素先进行最后输出链表,这样对应的这个链表继续遍历下一个元素,然后仍然这样比较即可。

具体代码如下:

class Solution{
    
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
         ListNode head = new ListNode(-1);
         ListNode dummy = head;
         while(list1 != null && list2 !=null){
             if(list1.val < list2.val){
                 head.next= list1;
                 list1 = list1.next;
             }else{
                 head.next = list2;
                 list2 = list2.next;
             }
         } 
         //此时list1和list2其中一个链表为null,head.next连接上非null链表
         head.next = (list1==null)?list2 : list1;
         //最后返回整个链表
         return dummy.next;
    }
}

复杂度分析

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

空间复杂度:O(1)。我们只需要常数的空间存放若干变量。

方法2: 递归法

相比较迭代法,递归法有些绕,具体代码如下:

class Solution{
    
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
          if(list1 == null){
               return list2;
          }else if(list2 == null){
               return list1;
          }else if(list1.val < list2.val){
               list1.next = mergeTwoLists(list1.next, list2);
               return list1;
          }else{
               list2.next = mergeTwoLists(list1, list2.next);
               return list2;
          }
    }
}

复杂度分析

时间复杂度:O(n + m),其中 n 和 m 分别为两个链表的长度。因为每次调用递归都会去掉 l1 或者 l2 的头节点(直到至少有一个链表为空),函数 mergeTwoList 至多只会递归调用每个节点一次。因此,时间复杂度取决于合并后的链表长度,即 O(n+m)。

空间复杂度:O(n + m),其中 n 和 m 分别为两个链表的长度。递归调用 mergeTwoLists 函数时需要消耗栈空间,栈空间的大小取决于递归调用的深度。结束递归调用时 mergeTwoLists 函数最多调用 n+m 次,因此空间复杂度为 O(n+m)。

你可能感兴趣的:(LeetCode刷题记录,链表,数据结构,算法,面试,dfs)