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()的形式