LC.21.合并两个有序链表

本文详细介绍了如何合并两个已排序的链表,分别使用迭代和递归两种方法。在迭代法中,通过创建虚拟头节点和辅助指针,逐个比较两个链表的节点并合并。在递归法中,通过递归调用实现相同的功能。两种方法都确保了合并后的链表仍然有序。

合并两个有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
在这里插入图片描述
思路:
解法一(迭代):
  借助两个指针,其分别指向l1的头节点、l2的头节点,每次比较两个链表中指针所指向的值,若l1.val >= l2.val,则选 l1 节点,并将其后移一位(l1 = l1.next);若l1.val < l2.val,则选 l2 节点,并将其后移一位(l2 = l2.next)。
  那么现在,问题来了,选出的节点要存放到哪里呢?
  关于链表的操作,我喜欢为链表设置虚拟头节点(dummyHead),并设置一个cur指针指向dummyHead,意为当前指针的指向。所以每次选出的节点就可存放为cur.next,每次存放完毕后,将cur后移一位(cur = cur.next)即可,方便下一次存放。当然也可以不设置dummyHead,直接设置head,只不过处理方式不同罢了。
  以上操作需要借助while循环来完成,那么循环终止条件是什么呢?这就是接下来我们要解决的问题。
  因为两个链表的长度可能不相等,那么当一条链表的所有节点都被选择后,剩下的另一条链表就无法进行上述的比较,会出现空指针错误,或者也可以认为此时已经不需要比较了,因为链表均为有序链表,使 cur .next 指向那条不为空的链表即可解题。所以说,我们的循环终止条件可以是 while(l1 != null && l2 != null) ,也可以是 while(l1 != null || l2 != null) ,只不过处理问题的位置不同,详情可以参考代码。
  while(l1 != null && l2 != null) 情况的代码:

 public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
     ListNode dummyHead = new ListNode(0);
     dummyHead.next = null;
     ListNode cur = dummyHead;
     while(l1 != null && l2 != null){
         if(l1.val <= l2.val){
             cur.next = l1;
             l1 = l1.next;
         }else{
             cur.next = l2;
             l2 = l2.next;
         }
         cur = cur.next;
     }
     if(l1 == null)
         cur.next = l2;
     
     if(l2 == null)
         cur.next = l1;
     
     return dummyHead.next;
 }

  while(l1 != null && l2 != null) 情况的代码:

public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
     ListNode dummyHead = new ListNode(0);
     dummyHead.next = null;
     ListNode cur = dummyHead;
     while(l1 != null || l2 != null){
         if(l1 == null){
             cur.next = l2;
             break;
         }
         if(l2 == null){
             cur.next = l1;
             break;
         }
         if(l1.val <= l2.val){
             cur.next = l1;
             l1 = l1.next;
         }else{
             cur.next = l2;
             l2 = l2.next;
         }
         cur = cur.next;
     }
     return dummyHead.next;
 }

解法二(递归):
  迭代解题完毕后,递归很容易就能想到,只不过迭代通过代码修改指针的方式,递归可以通过传递参数来完成,基本思想与迭代一致。

 public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
      ListNode dummyHead = new ListNode(0);
      dummyHead.next = null;
      ListNode cur = dummyHead;
      merge(cur,l1,l2);
      return dummyHead.next;
  }

  public void merge(ListNode cur,ListNode l1,ListNode l2){
      if(l1 == null){
          cur.next = l2;
          return;
      } 
      if(l2 == null){
          cur.next = l1;
          return;
      }
      if(l1.val <= l2.val){
          cur.next = l1;
          merge(cur.next,l1.next,l2);
      }else{
          cur.next = l2;
          merge(cur.next,l1,l2.next);
      }
  }

  总结:
在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值