86.分隔链表
新建两个链表,一个储存小于x的一个储存大于等于x的结点,然后拼接
class Solution(object):
def partition(self, head, x):
dummy1=ListNode()
dummy2=ListNode()
p1,p2=dummy1,dummy2
while head:
new=ListNode(head.val)
if head.val<x:
p1.next=new
p1=p1.next
else:
p2.next=new
p2=p2.next
head=head.next
p1.next=dummy2.next
return dummy1.next
148.排序链表
1.归并排序
不断二分链表,至子链表只包含一个或零个节点
然后两两合并升序链表
时间复杂度O(nlogn)空间复杂度O(logn)
class Solution:
"合并两个升序链表"
def mergeTwoLists(self,l1,l2):
dummy=ListNode()
p=dummy
while l1 and l2:
s1,s2=l1.val,l2.val
if s1<=s2:
p.next=l1
p=p.next
l1=l1.next
else:
p.next=l2
p=p.next
l2=l2.next
p.next=l2 if l2 else l1
return dummy.next
def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
##停止条件##
if head==None or head.next==None:return head
##使用双指针找链表中间节点##
s,f=head,head.next
while f and f.next:
s=s.next
f=f.next.next
##中间断开,分成左右两个子链表##
mid,s.next=s.next,None
left, right = self.sortList(head), self.sortList(mid)
##归并两个子链表##
return self.mergeTwoLists(left,right)
2.自下向上归并
思想:首先依次两两节点归并为长度为2的递增链表,然后两两归并长度为2的链表得到若干长为4的链表,再向上归并至原长度。
需要归并logn次每次需要遍历链表,时间复杂度为O(nlogn)
空间复杂度只需要存储几个指针向量,空间复杂度O(1)
class Solution:
def mergeTwoLists(self,l1,l2):
dummy=ListNode()
p=dummy
while l1 and l2:
s1,s2=l1.val,l2.val
if s1<=s2:
p.next=l1
p=p.next
l1=l1.next
else:
p.next=l2
p=p.next
l2=l2.next
p.next=l2 if l2 else l1
while p.next:
p=p.next
tail=p
return dummy.next,tail
def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
#记录链表长度#
len=0
l=head
while l:
len+=1
l=l.next
if len<2:return head
dummy=ListNode(next=head)
sublen=1
while sublen<=len:
tail=dummy
cur=dummy.next
while cur:
#向前遍历链表,得到长为sublen的两个子序列head1,head2,升序合并#
head1=cur
for i in range(sublen-1):
if cur.next==None:
break
cur=cur.next
head2=cur.next
cur.next=None
cur=head2
#注意断开尾节点,并注意cur遍历到最后为空时的边界#
if cur!=None:
for i in range(sublen-1):
if cur.next==None:
break
cur=cur.next
nex=cur.next
cur.next=None
cur=nex
#依次合并长为sublen的子链表,然后与原链表链接#
tail.next,tail=self.mergeTwoLists(head1,head2)
else:
tail.next,tail=self.mergeTwoLists(head1,head2)
sublen<<=1
return dummy.next
143.重排链表
从中间断开,将后半部分链表压入栈,然后前半部分链表每隔一个节点连接栈中最后一个元素,时间空间复杂度O(n)
后半部分逆序插入前半部分:同栈,不过空间复杂度O(1)
class Solution:
def reorderList(self, head: ListNode) -> None:
if head is None or head.next is None or head.next.next is None:return head
dummy=ListNode(next=head)
s,f=dummy,head
#找中间节点#
while f and f.next:
s=s.next
f=f.next.next
#从中间断开,后半部分节点数>=前半部分#
right=s.next
s.next=None
left=dummy.next
#将后半部分的节点压入栈内#
stack=[]
while right:
stack.append(right)
right=right.next
#将栈中的节点插入前半部分链表#
while left:
new=stack.pop()
cur=left
left=left.next
cur.next=new
new.next=left
#栈不为空的情况,将栈中剩余最后一个元素连接到链表尾#
if stack:
new.next=stack.pop()
new=new.next
new.next=None
return dummy.next
328. 奇偶链表
分别复制奇偶链表,拼接
只储存节点的指针,空间复杂度O(1)
class Solution(object):
def oddEvenList(self, head):
if not head:return head
dummy=ListNode(next=head)
p=dummy
dummy2=ListNode(next=head.next)
p2=dummy2
##使用try语句来处理边界##
try:
while 1:
p2.next=head.next
p2=p2.next
p.next=head
p=p.next
head=head.next.next
except:
p.next=dummy2.next
return dummy.next