21、合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
解:链表的基本应用
# 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, l1: ListNode, l2: ListNode) -> ListNode:
ans=ListNode(None)
result=ans
if not l1:
return l2
if not l2:
return l1
while l1 and l2:
if l1.val<l2.val:
ans.next=l1
ans=ans.next
l1=l1.next
else:
ans.next=l2
ans=ans.next
l2=l2.next
while l1:
ans.next=l1
ans=ans.next
l1=l1.next
while l2:
ans.next=l2
ans=ans.next
l2=l2.next
return result.next
运行时间为48 ms,击败了62.83%的用户,内存消耗为13.7 MB。
22、括号生成
数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
解法一:本题的想法是把每一次的增减左右括号单列出来分析,这时为了括号合法,必须保证左括号的数量不少于右括号的数量。
class Solution:
def generateParenthesis(self, n: int) -> List[str]:
ans=[["",0,0]]
result=[]
n2=len(ans)
while ans:
ans=self.addLeftandRight(ans,result,n)
result.sort()
return result
def addLeftandRight(self,alist,result,n):#一次增加左括号以及右括号的操作
n1=len(alist)
blist=[]
for i in range(n1):
left=alist[i][1]
right=alist[i][2]
s=alist[i][0]
curList=[]
for j in range(1,n-left):
for k in range(1,left+j+1-right):
curList.append([s+"("*j+")"*k,left+j,k+right])
result.append(s+"("*(n-left)+")"*(n-right))
blist=blist+curList
return blist
执行用时:40 ms击败了83.43%的用户;内存消耗:13.8 MB。
23、合并K个排序链表
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
解法一:用归并排序给lists排序,每一次拿出最小的加到ans里,然后最小的next插入剩下的已经排好的,继续操作。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
ans=ListNode(None)
result=ans
if not lists:
return None
lists=list(filter(lambda x: x!=None, lists))
if not lists:
return None
lists=self.mergeSort(lists)
while len(lists)>1:
ans.next=lists[0]
lists[0]=lists[0].next
if lists[0]==None:
del lists[0]
else:
lists=self.insertSort(lists)
ans=ans.next
while lists[0]:
ans.next=lists[0]
lists[0]=lists[0].next
ans=ans.next
return result.next
def mergeSort(self,alist):
if len(alist)>1:
mid=len(alist)//2
lefthalf=alist[:mid]
righthalf=alist[mid:]
self.mergeSort(lefthalf)
self.mergeSort(righthalf)
i=j=k=0
#拉链式交错把左右半部分从小到大加入到结果列表中
while i<len(lefthalf) and j<len(righthalf):
if lefthalf[i].val<righthalf[j].val:
alist[k]=lefthalf[i]
i=i+1
else:
alist[k]=righthalf[j]
j=j+1
k=k+1
#归并左半部分剩余项或右半部分剩余项
while i<len(lefthalf):
alist[k]=lefthalf[i]
i=i+1
k=k+1
while j<len(righthalf):
alist[k]=righthalf[j]
j=j+1
k=k+1
return alist
def insertSort(self,alist):#最小的ListNode取next后插入原本排序好的部分
index=0
for i in range(1,len(alist)):
if alist[index].val>alist[i].val:
temp=alist[index]
alist[index]=alist[i]
alist[i]=temp
index=i
else:
break
return alist
用时:144 ms,击败了28.11%的用户,内存消耗:16.5 MB
24、两两交换链表中的节点
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
解:本题的关键在于交换a,b两数是a.next,b.next以及last.next的交换,也就是说这里的交换是改变连接点的交换,不能通过直接赋值完成。理解了这点本题就只需要通过3个指针就能高效实现。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def swapPairs(self, head: ListNode) -> ListNode:
count=1
ans=ListNode(None)
last=ans
if not head or not head.next:
return head
last.next=head
first=head
second=head.next
while last.next and last.next.next:
first=last.next
second=last.next.next
first.next=second.next
second.next=first
last.next=second
last=last.next.next
return ans.next
执行用时:20 ms击败了100.00%的用户;内存消耗:13.6 MB。
25、 K 个一组翻转链表
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
解法:与上一道题的大体思路类似,可以先遍历一遍列表取长度,然后再K个一组添加到列表里,从右到左改变next值。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
count=0
ans=ListNode(None)
ans.next=head
last=ans
travel=ans
while travel.next:
travel=travel.next
count=count+1
if count<k:
return ans.next
for j in range(count//k):
alist=[]
result=last
for i in range(k):
alist.append(result.next)
result=result.next
last.next=alist[k-1]
alist[0].next=alist[k-1].next
for i in range(k-1,0,-1):
alist[i].next=alist[i-1]
for i in range(k):
last=last.next
return ans.next
运行时间52 ms, 击败了86.59%的用户;
内存消耗:14.5 MB,击败了38.33%的用户