合并两个有序链表10.21

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

# 合并两个有序链表
class ListNode(object):
    """定义一个链表节点类"""
    def __init__(self,val=0,next=None):
        self.val = val
        self.next = next

class LinkList(object):
    """定义一个链表类,该类使用上面定义的ListNode作为节点,通过在链表尾部添加节点来创建链表"""
    def __init__(self):
        self.head = None

    def initlist(self,data):
        self.head = ListNode(data[0])
        p = self.head
        for i in data[1:]:
            node = ListNode(i)
            p.next = node
            p = p.next

    def mergeTwoLists(self,l1,l2):
        """合并两个有序链表"""
        dummy = ListNode(-1)   # 虚拟头结点
        p = dummy  # p用于遍历的节点
        p1 = l1
        p2 = l2
        # 当两个链表都不为空时
        while p1 and p2 :
            # 比较p1和p2两个指针
            # 将值较小的节点接到p指针
            if p1.val < p2.val:
                p.next = p1
                p1 = p1.next
            else:
                p.next = p2
                p2 = p2.next
            # p指针不断前进
            p = p.next

        #如果链表1还有剩余节点
        if p1:
            p.next = p1
        #如果链表2还有剩余节点
        if p2:
            p.next = p2

        return dummy.next

    def printList(self):
        node = self.head
        while node:
            print(node.val)
            node = node.next


data1 = [1,2,4]
data2 = [2,3,5]
l1 = LinkList()
l2 = LinkList()
l1.initlist(data1)  
l2.initlist(data2)
l1.printList()
l2.printList()

merged_list = LinkList()  # 创建一个新的LinkList对对象merged_list
merged_list.head = l1.mergeTwoLists(l1.head, l2.head)  # 将l1和l2的头节点传递给mergeTwoLists,并将返回的结果赋给merged_list的头节点
merged_list.printList()
# 创建并初始化链表(方法一):
data1 = [1,2,4]
data2 = [2,3,5]
l1 = LinkList()
l2 = LinkList()
l1.initlist(data1)  
l2.initlist(data2)

# 创建并初始化链表(方法二):
l1 = LinkList()
l2 = LinkList()
l1.initlist([1,2,4])
l2.initlist([1,3,4])
# 合并两个链表
merged_list = LinkList()
merged_list.head = l1.mergeTwoLists(l1.head, l2.head)
# merged_list.head = l2.mergeTwoLists(l1.head, l2.head)

创建了一个新的LinkList对象merged_list,并将l1l2的头节点传递给mergeTwoLists方法,并将返回的结果赋值给merged_list的头节点。

在这两行代码中,l1.mergeTwoLists(l1.head, l2.head) 和 l2.mergeTwoLists(l1.head, l2.head),我们都是调用 mergeTwoLists 方法来合并 l1 和 l2 两个链表。

这两行代码的唯一区别在于我们调用 mergeTwoLists 方法的对象不同。在第一行代码中,我们在 l1 对象上调用 mergeTwoLists 方法,而在第二行代码中,我们在 l2 对象上调用 mergeTwoLists 方法。

然而,这两行代码的结果是相同的,因为 mergeTwoLists 方法的功能是合并两个链表,而不是依赖于它被调用的对象。无论我们在哪个对象上调用 mergeTwoLists 方法,它都会返回合并后的链表。

所以,你可以根据你的需要选择使用哪一行代码。如果你想要在 l1 对象上调用 mergeTwoLists 方法,你应该使用第一行代码。如果你想要在 l2 对象上调用 mergeTwoLists 方法,你应该使用第二行代码。

代码可视化动画

形象地理解,这个算法的逻辑类似于拉拉链,l1, l2 类似于拉链两侧的锯齿,指针 p 就好像拉链的拉索,将两个有序链表合并;或者说这个过程像蛋白酶合成蛋白质,l1, l2 就好比两条氨基酸,而指针 p 就好像蛋白酶,将氨基酸组合成蛋白质。

代码中还用到一个链表的算法题中是很常见的「虚拟头结点」技巧,也就是 dummy 节点。你可以试试,如果不使用 dummy 虚拟节点,代码会复杂一些,需要额外处理指针 p 为空的情况。而有了 dummy 节点这个占位符,可以避免处理空指针的情况,降低代码的复杂性。

么时候需要用虚拟头结点?我这里总结下:当你需要创造一条新链表的时候,可以使用虚拟头结点简化边界情况的处理。比如说,让你把两条有序链表合并成一条新的有序链表,是不是要创造一条新链表?再比你想把一条链表分解成两条链表,是不是也在创造新链表?这些情况都可以使用虚拟头结点简化边界情况的处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值