剑指--合并两个排序的链表

本文介绍两种方法合并两个已排序的链表,一种是非递归方式,通过引入伪头结点进行循环合并,另一种是递归方式,通过比较两链表头结点值,将较小者加入新链表。

剑指–合并两个排序的链表

1,题目:

在这里插入图片描述
2,思路:

方法一:引入伪头结点(思路还是正常思路)

引入伪头节点: 由于初始状态合并链表中无节点,因此循环第一轮时无法将节点添加到合并链表中。解决方案:初始化一个辅助节点 dum 作为合并链表的伪头节点,将各节点添加至 dum 之后

算法流程:

  • 1.初始化: 伪头节点 dum ,节点 cur 指向 dum。

  • 2.循环合并: 当l1或l2为空时跳出;

    • 当l1.val<l2.val 时: cur 的后继节点指定为 l1,并l1向前走一步;

    • 当 l1.val≥l2.val 时: cur 的后继节点指定为 l2,并l2向前走一步 ;

    • 节点 cur 向前走一步,即cur=cur.next 。

  • 3.合并剩余尾部: 跳出时有两种情况,即 l1为空 或l2为空。

    • 若 l1 !=null : 将l1添加至节点 cur 之后;

    • 否则: 将l2添加至节点 cur 之后。

  • 4.返回值: 合并链表在伪头节点 dum 之后,因此返回dum.next 即可。

下面是对应的图解:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

方法二:递归写法:

递归的写法:
递归算法 用一个新的指针来保存合并的代码 新链表的next指向下一个比较后的节点,如果是l1的节点则l1指针往后移动,如果是l2的节点则将l2的指针后移。

3,代码:

方法一:引入伪头结点(思路还是正常思路)

class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        /*

        引入伪头节点: 由于初始状态合并链表中无节点,因此循环第一轮时无法将节点添加到合并链表中。解决方案:初始化一个辅助节点 dum 作为合并链表的伪头节点,将各节点添加至 dum 之后。



        算法流程:
1.初始化: 伪头节点 dum ,节点 cur 指向 dum。
2.循环合并: 当l1或l2为空时跳出;
  当l1.val<l2.val 时: cur 的后继节点指定为 l1,并l1向前走一步;
  当 l1.val≥l2.val 时: cur 的后继节点指定为 l2,并l2向前走一步 ;
   节点 cur 向前走一步,即cur=cur.next 。
3.合并剩余尾部: 跳出时有两种情况,即 l1为空 或l2为空。
    若 l1 !=null : 将l1添加至节点 cur 之后;
  否则: 将l2添加至节点 cur 之后。
  4.返回值: 合并链表在伪头节点 dum 之后,因此返回dum.next 即可。


        */
        ListNode dum = new ListNode(0), cur = dum;//新建一个链表,并且cur指针指向头结点
        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;
        }
        cur.next = l1 != null ? l1 : l2;//这是合并剩下的节点
        return dum.next;
    }
}

这一个写法和上面的是一样的(非递归):

class Solution {
    public ListNode mergeTwoLists(ListNode linked1, ListNode linked2) {
        //非递归:

        /*
        因为链表是升序的,我们只需要遍历每个链表的头,比较一下哪个小就把哪个链表的头拿出来放到新的链表中,一直这样循环,直到有一个链表为空,然后我们再把另一个不为空的链表挂到新的链表中。


        */
            //下面4行是空判断
            if (linked1 == null)
                return linked2;
            if (linked2 == null)
                return linked1;
            ListNode dummy = new ListNode(0);
            ListNode curr = dummy;
            while (linked1 != null && linked2 != null) {
                //比较一下,哪个小就把哪个放到新的链表中
                if (linked1.val <= linked2.val) {
                    curr.next = linked1;
                    linked1 = linked1.next;
                } else {
                    curr.next = linked2;
                    linked2 = linked2.next;
                }
                curr = curr.next;
            }
            //然后把那个不为空的链表挂到新的链表中
            curr.next = linked1 == null ? linked2 : linked1;
            return dummy.next;
        }

}


方法二:递归写法:

class Solution {
    public ListNode mergeTwoLists(ListNode linked1, ListNode linked2) {
        //递归的写法
        //递归算法 用一个新的指针来保存合并的代码 新链表的next指向下一个比较后的节点,如果是l1的节点则l1指针往后移动,如果是l2的节点则将l2的指针后移。
            if (linked1 == null)
                return linked2;
            if (linked2 == null)
                return linked1;
            if (linked1.val < linked2.val) {
                linked1.next = mergeTwoLists(linked1.next, linked2);
                return linked1;
            } else {
                linked2.next = mergeTwoLists(linked1, linked2.next);
                return linked2;
            }
        }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值