class Solution:
def ReverseList(self , head: ListNode) -> ListNode:
if head == None:
return None
p = head
q = None
while p:
tmp = p.next
p.next = q
q = p
p = tmp
return q
时间复杂度:
O
(
n
)
O(n)
O(n),遍历链表一次
空间复杂度:
O
(
1
)
O(1)
O(1),无额外空间使用
class Solution:
def ReverseList(self , head: ListNode) -> ListNode:
if head == None or head.next == None:
return head
res = self.ReverseList(head.next)
head.next.next = head
head.next = None
return res
时间复杂度:
O
(
n
)
O(n)
O(n),相当于递归遍历链表
空间复杂度:
O
(
n
)
O(n)
O(n),递归栈深度为链表长度
n
n
n
class Solution:
def reverseBetween(self , head: ListNode, m: int, n: int) -> ListNode:
res = ListNode(-1) # 设置虚拟头结点
res.next = head
pre = res # 前序结点
cur = head # 当前结点
for i in range(1,m):
pre = cur
cur = cur.next
for i in range(m,n):
tmp = cur.next
cur.next = tmp.next
tmp.next = pre.next
pre.next = tmp
return res.next
时间复杂度:O(n),最坏情况下遍历全部链表
空间复杂度:O(1),无额外空间使用
如果 m == 1,就相当于反转链表的前 n 个元素;
如果 m != 1,我们把 head 的索引视为1,那么我们是想从第 m 个元素开始反转;如果把 head.next 的索引视为1,那么相对于 head.next 的反转区间应该是从第 m-1 个元素开始的。以此类推,就是一个递归问题。
对于每次反转,如果 n == 1,相当于只颠倒第一个节点;如果 n != 1,则进入后续节点,也是一个递归问题。
class Solution:
def __init__(self):
self.temp = None
def reverse(self, head: ListNode, n: int) -> ListNode:
if n == 1:
self.temp = head.next
return head
node = self.reverse(head.next, n-1)
head.next.next = head
head.next = self.temp
return node
def reverseBetween(self , head: ListNode, m: int, n: int) -> ListNode:
if m == 1:
return self.reverse(head,n)
node = self.reverseBetween(head.next, m-1, n-1)
head.next = node
return head
时间复杂度:O(n),最坏情况下遍历全部链表
空间复杂度:O(n),递归栈深度最坏为 n
class Solution:
def reverseKGroup(self , head: ListNode, k: int) -> ListNode:
tail = head
for i in range(0,k):
if tail == None:
return head
tail = tail.next
pre = None
cur = head
while cur != tail:
temp = cur.next
cur.next = pre
pre = cur
cur = temp
print(head.val)
head.next = self.reverseKGroup(tail, k)
return pre
时间复杂度:O(n),一共遍历链表 n 个结点
空间复杂度:O(n),递归栈最大深度为 n / k
class Solution:
def Merge(self , pHead1: ListNode, pHead2: ListNode) -> ListNode:
if pHead1 == None:
return pHead2
if pHead2 == None:
return pHead1
head = ListNode(-1)
cur = head
while pHead1 != None and pHead2 != None:
if pHead1.val <= pHead2.val:
cur.next = pHead1
pHead1 = pHead1.next
else:
cur.next = pHead2
pHead2 = pHead2.next
cur = cur.next
if pHead1 == None:
cur.next = pHead2
if pHead2 == None:
cur.next = pHead1
return head.next
时间复杂度:O(n),最坏情况遍历
2
n
2n
2n 个结点。
空间复杂度:O(1),无额外使用空间,新建的链表属于返回必要空间。
class Solution:
def Merge(self , pHead1: ListNode, pHead2: ListNode) -> ListNode:
if pHead1 == None:
return pHead2
if pHead2 == None:
return pHead1
if pHead1.val <= pHead2.val:
pHead1.next = self.Merge(pHead1.next, pHead2)
return pHead1
else:
pHead2.next = self.Merge(pHead1, pHead2.next)
return pHead2
时间复杂度:O(n),最坏相当于遍历两个链表每个结点一次
空间复杂度:O(n),递归栈最大长度为 n
class Solution:
def Merge(self , pHead1: ListNode, pHead2: ListNode) -> ListNode:
if pHead1 == None:
return pHead2
if pHead2 == None:
return pHead1
head = ListNode(-1)
cur = head
while pHead1 != None and pHead2 != None:
if pHead1.val <= pHead2.val:
cur.next = pHead1
pHead1 = pHead1.next
else:
cur.next = pHead2
pHead2 = pHead2.next
cur = cur.next
if pHead1 == None:
cur.next = pHead2
if pHead2 == None:
cur.next = pHead1
return head.next
def divideMerge(self, lists: List[ListNode], left: int, right: int) -> ListNode:
if left > right:
return None
elif left == right:
return lists[left]
mid = (int)((left+right)/2)
return self.Merge(self.divideMerge(lists, left, mid), self.divideMerge(lists, mid+1, right))
def mergeKLists(self , lists: List[ListNode]) -> ListNode:
return self.divideMerge(lists, 0, len(lists)-1)
时间复杂度:O(Nlogk),N 表示列表中所有链表的结点数量,K 表示链表的数量
空间复杂度:O(logk),递归会使用到 O(logk) 空间代价的栈空间
import heapq
class Solution:
def mergeKLists(self , lists: List[ListNode]) -> ListNode:
dummy = ListNode(0)
p = dummy
head = []
for i in range(len(lists)):
if lists[i]:
heapq.heappush(head, (lists[i].val, i))
lists[i] = lists[i].next
while head:
val, idx = heapq.heappop(head)
p.next = ListNode(val)
p = p.next
if lists[idx]:
heapq.heappush(head, (lists[idx].val, idx))
lists[idx] = lists[idx].next
return dummy.next
时间复杂度:O(Nlogk),N 表示列表中所有链表的结点数量,k 表示链表的数量,优先队列中的元素不超过 k 个,那么插入和删除的时间代价为 O(logk),这里最多有 N 个点,对于每个点都被插入删除各一次,故总的时间代价即渐进时间复杂度为 O(Nlogk)。
空间复杂度:O(k),优先队列中的元素不超过 k 个,故渐进空间复杂度为 O(k)。
class Solution:
def mergeKLists(self , lists: List[ListNode]) -> ListNode:
tmp = []
for head in lists:
while head:
tmp.append(head.val)
head = head.next
if not tmp:
return None
tmp.sort()
res = ListNode(-1)
cur = res
for i in range(len(tmp)):
cur.next = ListNode(tmp[i])
cur = cur.next
return res.next
时间复杂度:O(NlogN),N 表示列表中所有链表的结点数量,首先遍历所有结点 O(N),排序 O(NlogN)。
空间复杂度:O(N),辅助数组空间。