LeetCode刷题记录---21.合并两个有序链表

2025/6/29

题目(easy):

我的思路:

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

class Solution:
    def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
        #直接以此比较,比较得到小的加入新的结点链表中,并且该节点所在的原链表指针向后移动一位
        node1 = list1
        node2 = list2
        if(node1 == None and node2 == None):
            return None
        
        newList = None
        newListNodeIndex = None 

        while node1 != None or node2 != None :      #只要还有一个链表没有完全遍历完就继续循环
            #创建新结点
            newNode = ListNode(0,None)
            #给新节点的val赋值
            if node1 == None:
                newNode.val = node2.val
                node2 = node2.next
            elif node2 == None:
                newNode.val = node1.val
                node1 = node1.next
            elif node1.val <= node2.val:
                newNode.val = node1.val
                node1 = node1.next
            else:
                newNode.val = node2.val
                node2 = node2.next
            #将新节点接入新链表中
            if newList == None:
                newList = newNode
                newListNodeIndex = newList
            else:
                newListNodeIndex.next = newNode
                newListNodeIndex = newListNodeIndex.next

        return newList

时间复杂度:O(m+n)     [m,n分别是两个链表的长度]

空间复杂度:O(m+n)

可以改进的地方:

①其实可以不用新创建节点,这会增加空间复杂度

②是否为空的条件判断可以写的更简洁

③当一个链表指针指向None了的时候,其实剩下的可以直接指向另一个链表了,而不用继续遍历

改进思路:

其实完全可以不用想着创建一个新的链表,而是想着直接改变原有两个链表节点的指向

同时可以一开始就创建一个头结点,之后返回这个头节点的next即是排序好的节点

prehead作为头结点,负责最后返回结果

prev作为浮动的指针,负责移动到链表最后给链表添加新的节点

这样子,当比较出当前哪一个链表指针所在位置的值更小,令 prev的next指向它,之后这个链表指针向后移动,再使prev向后移动即可。

最后返回的是prehead.next 因为prehead本身是头结点,不负责记录数值

# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
        
        #先创建一个头结点
        prehead = ListNode(-1)
        prev = prehead

        if not list1:
            return list2
        elif not list2:
            return list1
        
        while list1 and list2:
            if list1.val <= list2.val:
                prev.next = list1
                list1 = list1.next
            else:
                prev.next = list2
                list2 = list2.next

            prev = prev.next

        prev.next = list1 if list1 is not None else list2

        return prehead.next

时间复杂度:O(m+n)

空间复杂度:O(1)

特别的思路:

递归!

观察可以发现,这个函数返回的是一个按升序合并后的链表,而去掉开头的元素的话,它依然是升序的链表。即为:子问题与原问题有相同的结构,所以可以考虑使用递归的方法来解决。

递归公式可以这样理解,如果当前

list1.val <= list2.val

那么,得到的结果链表一定是 [list1.val, [升序合并list1.next和list的链表]]

对list2同理

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
        #递归边界条件
        if not list1:
            return list2
        if not list2:
            return list1

        if list1.val <= list2.val:
            list1.next = self.mergeTwoLists(list1.next,list2)   #使list1当前所在位置指向的下一个节点是list1的下一个节点和list2按升序合并之后的列表即可
            return list1
        else:
            list2.next = self.mergeTwoLists(list1,list2.next)
            return list2

时间复杂度:O(m+n)

空间复杂度:O(m+n)[因为需要在堆栈里先存着等待递归的节点)

总结:

①做题目之前,先进行模式识别,观察问题是否能拆分成子问题,问题和子问题之间有什么关系,从而决定采用的方法策略

②对于链表,要利用链表的指向灵活性,不要当成普通的列表去想,毕竟链表是一种更灵活的列表,要利用它的特性来切入思考问题。没思路的时候,先画图

③Python里要调用类中的函数要用self.function()的形式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值