本次题目全部来自卡码网
110.字符串接龙
本题只需要求出最短路径的长度就可以了,不用找出具体路径。
所以这道题要解决两个问题:
- 图中的线是如何连在一起的
- 起点和终点的最短路径长度
首先题目中并没有给出点与点之间的连线,而是要我们自己去连,条件是字符只能差一个。所以判断点与点之间的关系,需要判断是不是差一个字符,如果差一个字符,那就是有连接。
然后就是求起点和终点的最短路径长度,这里无向图求最短路,广搜最为合适,广搜只要搜到了终点,那么一定是最短的路径。因为广搜就是以起点中心向四周扩散的搜索。
另外需要有一个注意点:
- 本题是一个无向图,需要用标记位,标记着节点是否走过,否则就会死循环!
- 使用set来检查字符串是否出现在字符串集合里更快一些
import collectionsif __name__ == '__main__':n = int(input())strSet = set()beginStr, endStr = input().strip().split()for _ in range(n):strSet.add(input())# 记录strSet里的字符串是否被访问过,同时记录路径长度visitMap = dict() # <记录的字符串,路径长度># 初始化队列que = collections.deque()que.append(beginStr)# 初始化visitMapvisitMap[beginStr] = 1while que:word = que.popleft()path = visitMap.get(word) # 这个字符串在路径中的长度# 开始在这个str中,挨个字符去替换for i in range(len(word)):newWord = word# 遍历26个字母for j in range(26):newWord = word[:i] + chr(j + ord('a')) + word[i+1:]if newWord == endStr: # 发现替换字母后,字符串与终点字符串相同print(path + 1) # 找到了路径exit()# 字符串集合里出现了newWord,并且newWord没有被访问过if newWord in strSet and newWord not in visitMap:# 添加访问信息,并将新字符串放到队列中visitMap[newWord] = path + 1que.append(newWord)# 没找到输出0print(0)
105. 有向图的完全可达性
两种深度优先搜索的算法主要是终止条件的位置不同
# 写法一:dfs 处理当前访问的节点
def dfs(graph, key, visited):if visited[key]:returnvisited[key] = Truekeys = graph[key]for key in keys:dfs(graph, key, visited)if __name__ == '__main__':n, m = map(int, input().strip().split())# 节点编号从1到n,所以申请 n+1 这么大的数组graph = [[] for _ in range(n + 1)] # 邻接表while m > 0:s, t = map(int, input().strip().split())# 使用邻接表 ,表示 s -> t 是相连的graph[s].append(t)m -= 1visited = [False] * (n + 1)dfs(graph, 1, visited);# 检查是否都访问到了for i in range(1, n + 1):if not visited[i]:print(-1)exit()print(1)# 写法二:处理下一个要访问的节点
def dfs(graph, key, visited):keys = graph[key]for key in keys:if not visited[key]:visited[key] = Truedfs(graph, key, visited)if __name__ == '__main__':n, m = map(int, input().strip().split())# 节点编号从1到n,所以申请 n+1 这么大的数组graph = [[] for _ in range(n + 1)] # 邻接表while m > 0:s, t = map(int, input().strip().split())# 使用邻接表 ,表示 s -> t 是相连的graph[s].append(t)m -= 1visited = [False] * (n + 1)visited[1] = Truedfs(graph, 1, visited)# 检查是否都访问到了for i in range(1, n + 1):if not visited[i]:print(-1)exit()print(1)
广度优先搜索
if __name__ == '__main__':n, m = map(int, input().strip().split())# 节点编号从1到n,所以申请 n+1 这么大的数组graph = [[] for _ in range(n + 1)] # 邻接表while m > 0:s, t = map(int, input().strip().split())# 使用邻接表 ,表示 s -> t 是相连的graph[s].append(t)m -= 1visited = [False] * (n + 1)visited[1] = Trueque = [1]# 广度优先搜索的过程while que:key = que.pop()keys = graph[key]for key in keys:if not visited[key]:que.append(key)visited[key] = True# 检查是否都访问到了for i in range(1, n + 1):if not visited[i]:print(-1)exit()print(1)
106. 岛屿的周长
解法一: 遍历每一个空格,遇到岛屿则计算其上下左右的空格情况。
如果该陆地上下左右的空格是有水域,则说明是一条边。如果该陆地上下左右的空格出界了,则说明是一条边。
if __name__ == '__main__':n, m = map(int, input().strip().split())grid = [[i for i in map(int, input().strip().split())] for _ in range(n)]dir = [(1, 0), (-1, 0), (0, 1), (0, -1)]result = 0for i in range(n):for j in range(m):if grid[i][j] == 1:for k in range(4):x = i + dir[k][0]y = j + dir[k][1]if x < 0 or x >= len(grid) or y < 0 or y >= len(grid[0]) or grid[x][y] == 0:result += 1print(result)
解法二: 计算出总的岛屿数量,总的变数为:岛屿数量 * 4
因为有一对相邻两个陆地,边的总数就要减2。那么只需要在计算出相邻岛屿的数量就可以了,相邻岛屿数量为cover。
result = 岛屿数量 * 4 - cover * 2;
if __name__ == '__main__':n, m = map(int, input().strip().split())grid = [[i for i in map(int, input().strip().split())] for _ in range(n)]_sum = 0 # 陆地数量cover = 0 # 相邻数量for i in range(n):for j in range(m):if grid[i][j] == 1:_sum += 1 # 统计总的陆地数量# 统计上边相邻陆地if i - 1 >= 0 and grid[i-1][j] == 1:cover += 1# 统计左边相邻陆地if j - 1 >= 0 and grid[i][j-1] == 1:cover += 1# 为什么没统计下边和右边? 因为避免重复计算print(_sum * 4 - cover * 2)