并查集模板
class UnionFind ( ) : def __init__ ( self) : self. roots = { } self. setCnt = 0 self. rootSizes = { } def add ( self, x) : if x not in self. roots: self. roots[ x] = xself. rootSizes[ x] = 1 self. setCnt += 1 def find ( self, x) : root = xwhile root != self. roots[ root] : root = self. roots[ root] while x != root: temp = self. roots[ x] self. roots[ x] = rootx = tempreturn rootdef union ( self, x, y) : rootx, rooty = self. find( x) , self. find( y) if rootx != rooty: if self. rootSizes[ rootx] < self. rootSizes[ rooty] : self. roots[ rootx] = rootyself. rootSizes[ rooty] += self. rootSizes[ rootx] else : self. roots[ rooty] = rootxself. rootSizes[ rootx] += self. rootSizes[ rooty] self. setCnt -= 1
二分查找(左闭右开)
def lower_bound ( nums, target) : left, right= 0 , len ( nums) while left< right: mid= ( right- left) // 2 + leftif nums[ mid] < target: left= mid+ 1 else : right= mid return left
二叉树遍历
二叉树中序遍历和前序遍历(栈)
def inorder ( root) : stack= [ ] node= rootwhile stack or node: while node: print ( node. val) stack. append( node) node= node. leftnode= stack. pop( ) print ( node. val) node= node. right
二叉树后序遍历(栈)
def afterOrder ( root) : result= [ ] stack= [ ] prev= None node= rootwhile stack or node: while node: stack. append( node) node= node. leftnode= stack. pop( ) if node. right is None or node. right== prev: result. append( node. val) prev= nodenode= None else : stack. append( node) node= node. rightreturn result
二叉树的Morris算法前序遍历和中序遍历
def preOrderByMorris ( root) - > list [ int ] : if root is None : return [ ] cur = rootwhile cur: if not cur. left: print ( cur. val) cur = cur. rightelse : rightMost = cur. leftwhile rightMost. right is not None and rightMost. right is not cur: rightMost = rightMost. rightif rightMost. right is None : print ( cur. val) rightMost. right = curcur = cur. leftelse : rightMost. right = None cur = cur. right
字典树/前缀树模板
class Trie : def __init__ ( self) : self. sons= { } self. end= False def insert ( self, word) : cur= selffor c in word: if c not in cur. sons: cur. sons[ c] = Trie( ) cur= cur. sons[ c] cur. end= True def find ( self, word) : cur= selffor c in word: if c not in cur. sons: return 0 cur= cur. sons[ c] return 2 if cur. end else 1 def display ( self) : que= [ self] print ( "->" ) while que: for i in range ( len ( que) ) : node= que. pop( 0 ) for key, subNode in node. sons. items( ) : print ( key, end= " " ) que. append( subNode) print ( "" ) print ( "=>" )
辗转相除法求最大公约数
def gcd ( m, n) : maxVal, minVal= max ( m, n) , min ( m, n) r= maxVal% minValwhile r!= 0 : maxVal= minValminVal= rr= maxVal% minValreturn minVal
树状数组模板
树状数组(求区间和)
class TreeArr ( ) : def __init__ ( self, length) : self. length= lengthself. arr= [ 0 ] * self. lengthdef lowerbit ( self, x) : return x& ( - x) def add ( self, index: int , val: int ) - > None : while index < self. length: self. arr[ index] += valindex = index + self. lowerbit( index + 1 ) def query ( self, index: int ) - > int : sum_ = 0 while index >= 0 : sum_ += self. arr[ index] index -= self. lowerbit( index + 1 ) return sum_def sumRange ( self, left: int , right: int ) - > int : pass
树状数组(求区间最大值)
class MaxTreeArr ( ) : def __init__ ( self, n: int ) : self. n = nself. nums = [ - inf] * nself. arr = [ - inf] * ndef lowerbit ( self, x: int ) - > int : return x & ( - x) def update ( self, index: int , val: int ) - > None : self. nums[ index] = max ( self. nums[ index] , val) while index < self. n: self. arr[ index] = max ( self. arr[ index] , val) index += self. lowerbit( index + 1 ) def queryMax ( self, left: int , right: int ) - > int : ans = - infindex = rightwhile index >= left: l = index - self. lowerbit( index + 1 ) + 1 if l >= left: ans = max ( ans, self. arr[ index] ) index = l - 1 else : ans = max ( ans, self. nums[ index] ) index -= 1 return ans
线段树模板
求区间最大值的线段树模板
class SegmentTreeToMax ( ) : def __init__ ( self, n: int ) : self. n = n self. arr = [ - inf] * ( 4 * n) def change ( self, index: int , val: int , node: int , start: int , end: int ) - > None : if index == start and index == end: self. arr[ node] = max ( self. arr[ node] , val) return mid = ( end - start) // 2 + startif index <= mid: self. change( index, val, 2 * node + 1 , start, mid) else : self. change( index, val, 2 * node + 2 , mid + 1 , end) self. arr[ node] = max ( self. arr[ 2 * node + 1 ] , self. arr[ 2 * node + 2 ] ) def rangeMax ( self, left: int , right: int , node: int , start: int , end: int ) - > int : if left == start and right == end: return self. arr[ node] mid = ( end - start) // 2 + startif right <= mid: return self. rangeMax( left, right, 2 * node + 1 , start, mid) elif left > mid: return self. rangeMax( left, right, 2 * node + 2 , mid + 1 , end) return max ( self. rangeMax( left, mid, 2 * node + 1 , start, mid) , self. rangeMax( mid + 1 , right, 2 * node + 2 , mid + 1 , end) ) def update ( self, index: int , val: int ) - > None : return self. change( index, val, 0 , 0 , self. n - 1 ) def getRangeMax ( self, left: int , right: int ) - > int : return self. rangeMax( left, right, 0 , 0 , self. n - 1 )
带懒标记的线段树(求区间和)
class SegmentTreeToSumWithLazy ( ) : def __init__ ( self, nums: list [ int ] ) : self. n = len ( nums) self. tree = [ 0 ] * ( self. n * 4 ) self. lazy = [ 0 ] * ( self. n * 4 ) self. build( nums, 0 , 0 , self. n - 1 ) def build ( self, nums: list [ int ] , node: int , start: int , end: int ) - > None : if start == end: self. tree[ node] = nums[ start] return mid = ( end - start) // 2 + startself. build( nums, node * 2 + 1 , start, mid) self. build( nums, node * 2 + 2 , mid + 1 , end) self. tree[ node] = self. tree[ node * 2 + 1 ] + self. tree[ node * 2 + 2 ] def pushDown ( self, node: int , start: int , end: int ) - > None : if self. lazy[ node] == 0 : return mid = ( end - start) // 2 + startleftChild = node * 2 + 1 rightChild = node * 2 + 2 self. tree[ leftChild] += self. lazy[ node] * ( mid - start + 1 ) self. lazy[ leftChild] += self. lazy[ node] self. tree[ rightChild] += self. lazy[ node] * ( end - mid) self. lazy[ rightChild] += self. lazy[ node] self. lazy[ node] = 0 def rangeUpdate ( self, value: int , left: int , right: int , node: int , start: int , end: int ) - > None : if left > end or right < start: return if left <= start and right >= end: self. tree[ node] += value * ( end - start + 1 ) self. lazy[ node] += valuereturn self. pushDown( node, start, end) leftChild, rightChild = node * 2 + 1 , node * 2 + 2 mid = ( end - start) // 2 + startself. rangeUpdate( value, left, right, leftChild, start, mid) self. rangeUpdate( value, left, right, rightChild, mid + 1 , end) self. tree[ node] = self. tree[ leftChild] + self. tree[ rightChild] def pointUpdate ( self, index: int , value: int , node: int , start: int , end: int ) - > None : self. rangeUpdate( value, index, index, node, start, end) def rangeSum ( self, left: int , right: int , node: int , start: int , end: int ) - > int : if left > end or right < start: return 0 if left <= start and right >= end: return self. tree[ node] self. pushDown( node, start, end) mid = ( end - start) // 2 + startreturn self. rangeSum( left, right, node * 2 + 1 , start, mid) + self. rangeSum( left, right, node * 2 + 2 , mid + 1 , end)
带懒标记的线段树(求区间最大值)
inf = float ( "inf" )
class SegmentTreeToMaxWithLazy ( ) : def __init__ ( self, nums: list [ int ] ) : self. n = len ( nums) self. tree = [ 0 ] * ( self. n * 4 ) self. lazy = [ 0 ] * ( self. n * 4 ) self. build( nums, 0 , 0 , self. n - 1 ) def build ( self, nums: list [ int ] , node: int , start: int , end: int ) - > None : if start == end: self. tree[ node] = nums[ start] return mid = ( end - start) // 2 + startself. build( nums, node * 2 + 1 , start, mid) self. build( nums, node * 2 + 2 , mid + 1 , end) self. tree[ node] = max ( self. tree[ node * 2 + 1 ] , self. tree[ node * 2 + 2 ] ) def pushDown ( self, node: int , start: int , end: int ) - > None : if self. lazy[ node] == 0 : return mid = ( end - start) // 2 + startleftChild = node * 2 + 1 rightChild = node * 2 + 2 self. tree[ leftChild] += self. lazy[ node] self. lazy[ leftChild] += self. lazy[ node] self. tree[ rightChild] += self. lazy[ node] self. lazy[ rightChild] += self. lazy[ node] self. lazy[ node] = 0 def rangeUpdate ( self, value: int , left: int , right: int , node: int , start: int , end: int ) - > None : if left > end or right < start: return if left <= start and right >= end: self. tree[ node] += valueself. lazy[ node] += valuereturn self. pushDown( node, start, end) leftChild, rightChild = node * 2 + 1 , node * 2 + 2 mid = ( end - start) // 2 + startself. rangeUpdate( value, left, right, leftChild, start, mid) self. rangeUpdate( value, left, right, rightChild, mid + 1 , end) self. tree[ node] = max ( self. tree[ leftChild] , self. tree[ rightChild] ) def pointUpdate ( self, index: int , value: int , node: int , start: int , end: int ) - > None : self. rangeUpdate( value, index, index, node, start, end) def rangeMax ( self, left: int , right: int , node: int , start: int , end: int ) - > int : if left > end or right < start: return - infif left <= start and right >= end: return self. tree[ node] self. pushDown( node, start, end) mid = ( end - start) // 2 + startreturn max ( self. rangeMax( left, right, node * 2 + 1 , start, mid) , self. rangeMax( left, right, node * 2 + 2 , mid + 1 , end) )
拓扑排序算法
from typing import Dict, List
from collections import deque
def topoSort ( adjListGraph: List[ List[ int ] ] , inDegreeList: List[ int ] ) : que= deque( ) length= len ( adjListGraph) for node in range ( length) : inDegree= inDegreeList[ node] if inDegree== 0 : que. append( node) result= [ ] while que: node= que. popleft( ) result. append( node) for subNode in adjListGraph[ node] : inDegreeList[ subNode] -= 1 if inDegreeList[ subNode] == 0 : que. append( subNode) return result if len ( result) == len ( adjListGraph) else [ ]
最小生成树算法
prim算法
import heapq
from typing import Dict, List
def primMinSpanningTree ( graph: Dict[ object , List[ List] ] ) : minWeightsSum, treeEdges= 0 , [ ] firstNode= list ( graph. keys( ) ) [ 0 ] visited= set ( [ firstNode] ) neighEdgesHeap= [ item+ [ firstNode] for item in graph[ firstNode] ] heapq. heapify( neighEdgesHeap) while neighEdgesHeap: weight, node, startNode= heapq. heappop( neighEdgesHeap) if node in visited: continue minWeightsSum+= weighttreeEdges. append( [ startNode, node, weight] ) visited. add( node) for nextWeight, nextNode in graph[ node] : if nextNode not in visited: heapq. heappush( neighEdgesHeap, [ nextWeight, nextNode, node] ) return minWeightsSum, treeEdges, visited
单源最短路径算法
dijkstra算法
from typing import List
import heapq
inf= float ( "inf" )
def dijkstraMinDist ( graph: List[ List[ List] ] , startNode: int ) : length= len ( graph) distances= [ inf] * length distances[ startNode] = 0 pathsPrevs= [ - 1 ] * length distsHeap= [ [ 0 , startNode] ] while distsHeap: dist, node= heapq. heappop( distsHeap) if dist> distances[ node] : continue for edgeWeight, subNode in graph[ node] : thisDist= edgeWeight+ distances[ node] if thisDist< distances[ subNode] : distances[ subNode] = thisDistpathsPrevs[ subNode] = nodeheapq. heappush( distsHeap, [ thisDist, subNode] ) return distances, pathsPrevs
spfa算法
from collections import deque
def spfa ( graph: list [ list [ int ] ] , start: int , end: int ) : inf = float ( "inf" ) n = len ( graph) que = deque( [ start] ) visited = [ False ] * nvisited[ start] = True dists = [ inf] * ndists[ start] = 0 paths = [ None ] * npaths[ start] = - 1 cnt = [ 0 ] * ncnt[ 0 ] = 1 while que: for _ in range ( len ( que) ) : node = que. popleft( ) visited[ node] = False for neighNode, weight in graph[ node] : if dists[ neighNode] > dists[ node] + weight: dists[ neighNode] = dists[ node] + weightpaths[ neighNode] = nodeif not visited[ neighNode] : que. append( neighNode) visited[ neighNode] = True cnt[ neighNode] += 1 if cnt[ neighNode] > n: raise Exception( "存在负环,请检查图是否有错误!" ) return dists, paths
二分图最大匹配数算法
匈牙利算法
from collections import defaultdict
def hungarian ( graph: dict [ int , list [ int ] ] , leftNodes: list [ int ] ) - > int : rightMatch = { } def dfs ( u: int ) - > bool : for v in graph[ u] : if not visited[ v] : visited[ v] = True if v not in rightMatch or dfs( rightMatch[ v] ) : rightMatch[ v] = ureturn True return False ans = 0 for u in leftNodes: visited = defaultdict( bool ) if dfs( u) : ans += 1 return ans
Hopcroft-karp算法
from collections import deque
def hopcroftKarp ( graph: list [ list [ int ] ] , leftNodes: list [ int ] ) : inf = float ( "inf" ) match_ = { } dist = { } def bfs ( ) : queue = deque( ) for u in leftNodes: if u not in match_: dist[ u] = 0 queue. append( u) else : dist[ u] = inffound = False while queue: u = queue. popleft( ) for v in graph[ u] : if v not in match_: found = True elif dist[ match_[ v] ] == inf: queue. append( match_[ v] ) dist[ match_[ v] ] = dist[ u] + 1 return founddef dfs ( u) : for v in graph. get( u, [ ] ) : if v not in match_ or ( dist. get( match_[ v] , inf) == dist[ u] + 1 and dfs( match_[ v] ) ) : match_[ v] = umatch_[ u] = vreturn True dist[ u] = infreturn False ans = 0 while bfs( ) : for u in leftNodes: if u not in match_: if dfs( u) : ans += 1 return ans
懒删除小根堆模板
from collections import defaultdict
from heapq import heappush, heappop, heappushpop
class LazyMinHeap : def __init__ ( self) : self. heap = [ ] self. size = 0 self. sum = 0 self. cnts = defaultdict( int ) self. delayDelete = defaultdict( int ) def prune ( self) : while self. heap: topVal = self. heap[ 0 ] if self. delayDelete[ topVal] > 0 : heappop( self. heap) self. delayDelete[ topVal] -= 1 else : break def delete ( self, val: int ) : if self. cnts[ val] > 0 : self. cnts[ val] -= 1 self. delayDelete[ val] += 1 self. size -= 1 self. sum -= valreturn True return False def empty ( self) : self. prune( ) return len ( self. heap) == 0 def top ( self) : if self. empty( ) : return return self. heap[ 0 ] def push ( self, val: int ) : if self. delayDelete[ val] > 0 : self. delayDelete[ val] -= 1 else : heappush( self. heap, val) self. cnts[ val] += 1 self. sum += valself. size += 1 def pop ( self) : if self. empty( ) : return val = heappop( self. heap) self. cnts[ val] -= 1 self. size -= 1 self. sum -= valreturn valdef __str__ ( self) : return f"size= { self. size} \nsum= { self. sum } \ndelayDelete= { self. delayDelete} \ncnts= { self. cnts} \nheap= { self. heap} \n"