代码随想录算法训练营day67 | 110.字符串接龙、105. 有向图的完全可达性、106. 岛屿的周长

本次题目全部来自卡码网

110.字符串接龙

本题只需要求出最短路径的长度就可以了,不用找出具体路径。

所以这道题要解决两个问题:

  • 图中的线是如何连在一起的
  • 起点和终点的最短路径长度

首先题目中并没有给出点与点之间的连线,而是要我们自己去连,条件是字符只能差一个。所以判断点与点之间的关系,需要判断是不是差一个字符,如果差一个字符,那就是有连接。

然后就是求起点和终点的最短路径长度,这里无向图求最短路,广搜最为合适,广搜只要搜到了终点,那么一定是最短的路径。因为广搜就是以起点中心向四周扩散的搜索。

另外需要有一个注意点:

  • 本题是一个无向图,需要用标记位,标记着节点是否走过,否则就会死循环!
  • 使用set来检查字符串是否出现在字符串集合里更快一些
import collections

if __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)

    # 初始化visitMap
    visitMap[beginStr] = 1

    while 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 + 1
                    que.append(newWord)
    # 没找到输出0
    print(0)

105. 有向图的完全可达性

两种深度优先搜索的算法主要是终止条件的位置不同

# 写法一:dfs 处理当前访问的节点
def dfs(graph, key, visited):
    if visited[key]:
        return
    visited[key] = True
    keys = 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 -= 1

    visited = [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] = True
            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 -= 1

    visited = [False] * (n + 1)
    visited[1] = True
    dfs(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 -= 1

    visited = [False] * (n + 1)
    visited[1] = True
    que = [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 = 0
    for 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 += 1
    print(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)

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值