【图】
1. 实现有向图、无向图、有权图、无权图的邻接矩阵和邻接表表示方法
class Undigraph(object):
def __init__(self, vertex_num): self.v_num = vertex_num self.adj_tbl = [] for i in range(self.v_num + 1): self.adj_tbl.append([]) def add_edge(self, s, t): if s > self.v_num or t > self.v_num: return False self.adj_tbl[s].append(t) self.adj_tbl[t].append(s) return True def __len__(self): return self.v_num def __getitem__(self, ind): if ind > self.v_num: raise IndexError("No Such Vertex!") return self.adj_tbl[ind] def __repr__(self): return str(self.adj_tbl) def __str__(self): return str(self.adj_tbl) class Digraph(object): def __init__(self, vertex_num): self.v_num = vertex_num self.adj_tbl = [] for i in range(self.v_num + 1): self.adj_tbl.append([]) def add_edge(self, frm, to): if frm > self.v_num or to > self.v_num: return False self.adj_tbl[frm].append(to) def __len__(self): return self.v_num def __getitem__(self, ind): if ind > self.v_num: raise IndexError("No such vertex!") return self.ajd_tbl[ind] def __repr__(self): return str(self.adj_tbl) def __str__(self): return str(self.adj_tbl)
2. 实现图的深度优先搜索、广度优先搜索
#dfs from pythonds.graphs import Graph class DFSGraph(Graph): def __init__(self): super().__init__() self.time = 0 def dfs(self): for aVertex in self: aVertex.setColor('white') aVertex.setPred(-1) for aVertex in self: if aVertex.getColor() == 'white': self.dfsvisit(aVertex) def dfsvisit(self,startVertex): startVertex.setColor('gray') self.time += 1 startVertex.setDiscovery(self.time) for nextVertex in startVertex.getConnections(): if nextVertex.getColor() == 'white': nextVertex.setPred(startVertex) self.dfsvisit(nextVertex) startVertex.setColor('black') self.time += 1 startVertex.setFinish(self.time) #bfs from pythonds.graphs import Graph, Vertex from pythonds.basic import Queue def bfs(g,start): start.setDistance(0) start.setPred(None) vertQueue = Queue() vertQueue.enqueue(start) while (vertQueue.size() > 0): currentVert = vertQueue.dequeue() for nbr in currentVert.getConnections(): if (nbr.getColor() == 'white'): nbr.setColor('gray') nbr.setDistance(currentVert.getDistance() + 1) nbr.setPred(currentVert) vertQueue.enqueue(nbr) currentVert.setColor('black')
3. 实现 Dijkstra 算法、A* 算法
def find_lowest_cost_node(costs): lowest_cost = float("inf") lowest_cost_node = None # Go through each node. for node in costs: cost = costs[node] # If it's the lowest cost so far and hasn't been processed yet... if cost < lowest_cost and node not in processed: # ... set it as the new lowest-cost node. lowest_cost = cost lowest_cost_node = node return lowest_cost_node # Find the lowest-cost node that you haven't processed yet. node = find_lowest_cost_node(costs) # If you've processed all the nodes, this while loop is done. while node is not None: cost = costs[node] # Go through all the neighbors of this node. neighbors = graph[node] for n in neighbors.keys(): new_cost = cost + neighbors[n] # If it's cheaper to get to this neighbor by going through this node... if costs[n] > new_cost: # ... update the cost for this node. costs[n] = new_cost # This node becomes the new parent for this neighbor. parents[n] = node # Mark the node as processed. processed.append(node) # Find the next node to process, and loop. node = find_lowest_cost_node(costs)
4. 实现拓扑排序的 Kahn 算法、DFS 算法
class Solution: def Dfs(self, G): for u in G.V: u.color = 'white' u.pi = None global time time = 0 for u in G.V: if u.color == 'white': self.DfsVisit(G, u) def DfsVisit(self, G, u): global time time = time + 1 u.d = time u.color = 'gray' for v in u.adj: if v.color == 'white': self.DfsVisit(G, v) v.pi = u u.color = 'black' time = time + 1 u.f = time def TopologicalSort(self, G): LinkedList = Vertex('#') self.Dfs(G) G.V.sort(key=lambda v:v.f) for v in G.V: v.next = LinkedList.next LinkedList.next = v return LinkedList
练习:
1. 岛屿的个数 https://leetcode-cn.com/problems/number-of-islands/description/
思路:深度优先搜索递归
class Solution: def numIslands(self, grid: List[List[str]]) -> int: #遍历所有格点,每当发现陆地就用dfs递归沉没它周围的陆地,那么我们发现陆地的次数就是岛屿数 #try-except异常处理 try: m = len(grid) n = len(grid[0]) except: return 0 def dfs(i, j): if 0 <= i < m and 0 <= j < n and int(grid[i][j]): grid[i][j] = '0' for a, b in ((1, 0), (0, -1), (-1, 0), (0, 1)): dfs(i + a, j + b) r = 0 for i in range(m): for j in range(n): r += int(grid[i][j]) dfs(i, j) # 调用dfs沉没一整块陆地 return r
2. 有效的数独 https://leetcode-cn.com/problems/valid-sudoku/
思路:集合set
class Solution: def isValidSudoku(self, board: List[List[str]]) -> bool: #分别判断行,列,3*3所组成的list里面是否有重复值 for line in board: l = [value for value in line if value !='.'] if len(set(l)) != len(l): return False for cursor in range(9): l=[board[i][cursor] for i in range(0,9) if board[i][cursor] !='.'] if len(set(l)) != len(l): return False for i in [2,5,8]: for j in [2,5,8]: l = [board[i-m][j-n] for m in range(3) for n in range(3) if board[i-m][j-n] !="."] if len(set(l))!=len(l): return False return True