合并两个有序链表

LeetCode21. 合并两个有序链表

问题描述

输入两个单调递增的链表,输出两个链表合成后的链表,我们需要合成后的链表满足单调不减规则。

示例:

输入: {1,3,5},{2,4,6}

返回值: {1,2,3,4,5,6}

分析问题

既然给定的两个链表都是有序的,那么我们可以判断两个链表的头结点的值的大小,将较小值的结点添加到结果中,然后将对应链表的结点指针后移一位,循环往复,直到有一个链表为空为止。

由于链表是有序的,所以循环终止时,那个非空的链表中的元素都比前面已经合并的链表中的元素大,所以,我们只需要简单地将非空链表接在合并链表的后面,并返回合并链表即可。

首先我们需要先创建一个哨兵节点,然后将prehead指向链表l1和l2中比较小的一个。如果相等的话,指向任意一个即可。然后将较小值对应的链表的指针后移一位。

image-20210929111544031

image-20210929111101067

image-20210929111232244

image-20210929111251873

更多题解,关注公众号《程序员学长》,让你进大厂不走弯路

我们下面来看一下代码实现。

def mergeTwoLists(self, l1, l2):
        #合并后链表的哨兵结点
        head=ListNode(-1,None)
        pre=head
        #循环遍历,将两个链表中的较小值插入到合并后的链表中
        while l1 and l2:
            if l1.val <= l2.val:
                pre.next=l1
                l1=l1.next
            else:
                pre.next=l2
                l2=l2.next
            pre=pre.next
        #将剩余的非空链表插入到合并链表的后面
        if l1:
            pre.next=l1
        else:
            pre.next=l2

        return head.next

其实,我们这里也可以使用递归的方式来实现。

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

class Solution:
    def mergeTwoLists(self, l1, l2):
        #链表l1为空,不需要合并,直接返回l2
        if(l1==None):
            return l2
        #同理,l2为空,直接返回l1即可    
        if(l2==None):
            return l1

        if(l1.val<=l2.val):
            l1.next=self.mergeTwoLists(l1.next,l2)
            return l1
        else:
            l2.next=self.mergeTwoLists(l1,l2.next)
            return l2

问题升级

LeetCode23. 合并K个升序链表

下面,我们来把问题升级一下,将两个有序链表合并改成多个有序链表合并,我们来看一下题目。

给定一个有序链表, 其中每个节点也表示有一个有序链表。结点包含两个类型的指针:

  1. 指向主链表中下一个结点的指针。
  2. 指向以此结点为头的链表。

示例如下所示:

  4 ->  9 -> 15 -> 19
  |     |     |     |
  7    13    18    28
  |           |     |
  8          21    37
  |                
  20               
  
 实现函数flatten(),该函数用来将链表扁平化成单个链表。例如上面的链表,输出链表为
 
  4 -> 7 -> 8 -> 9 -> 13 -> 15 -> 18 ->19 -> 20 -> 21 -> 28 -> 37 

题目要求我们把二维有序链表合并成一个单链表,我们来把问题简化一下,假设主链表只有两个节点,即这个二维链表变成如下所示。

 4 ->  9 
  |     |     
  7    13           旋转一下         4 -> 7 -> 8 -> 20
  |               ---------->       |
  8                                 9 -> 13
  |                
  20   

这不就是我们上面讲的两个有序链表合并吗?那如果主链表有多个节点呢?我们可以使用归并的思想,逐个去合并就好了,如下图所示。

image-20210919173056276

下面我们来看一下代码如何实现。

class ListNode:
    def __init__(self, val=0, right=None, down=None):
        self.val = val
        self.right = right
        self.down = down

class Solution:
    def mergeTwoLists(self, l1, l2):
        #如果有一个链表为空,则合并后的链表就是另外一个
        if(l1==None):
            return l2
        if(l2==None):
            return l1

        if(l1.val<=l2.val):

            l1.down=self.mergeTwoLists(l1.down,l2)
            return l1
        else:
            l2.down=self.mergeTwoLists(l1,l2.down)
            return l2


    def flatten(self,root):
        if root== None or root.right == None:
            return root
        #把root->right 看作是已经有序的单链表,
        #然后通过递归来进行归并
        return self.mergeTwoLists(root, self.flatten(root.right))