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

1. 110. 字符串接龙

题目链接:110. 字符串接龙
文档讲解: 代码随想录

本题只需要求出最短路径的长度,不用找出具体路径。这道题要解决两个问题,图中的线是如何连在一起的,以及起点和终点的最短路径长度。首先题目中并没有给出点与点之间的连线,而是要自己连,条件是字符只能差一个。然后求最短路径长度,属于无向图求最短路,适合用广搜,广搜只要搜到了终点,那就是最短路径。同时,本题是个无向图,需要标记节点是否被访问过,不然会陷入死循环,使用集合来检查字符串是否出现在字符串集合中更快一点。

from collections import deque
def bfs(biginStr,endStr,srtList,visited):
    que = deque()
    que.append(biginStr)
    while que:
        word = que.popleft()
        path = visited[word]
        #开始进行替换
        for i in range(len(word)):
            #遍历26个字母
            for j in range(26):
                newword = word[:i] + chr(ord('a') + j) + word[i+1:]
                #替换后的字符串与终点字符一样
                if newword == endStr:
                    return path + 1 
                #字符串自核中出现了newword,且没有被访问过
                if newword in srtList and newword not in visited:
                    visited[newword] = path + 1 
                    que.append(newword)
    return 0 

n = int(input())
biginStr, endStr = input().split()
#集合,便于快速查找
srtList = set()
for _ in range(n):
    srtList.add(input())
#记录访问过的字符串,值为路径长度
visited = {}
visited[biginStr] = 1
res = bfs(biginStr,endStr,srtList,visited)
print(res)

2. 105.有向图的完全可达性

题目链接:105.有向图的完全可达性
文档讲解: 代码随想录
用矩阵记录访问过的节点,深搜一遍之后,如果所有节点都被访问过,则输出1。本题是有向图搜索全路径的问题,dfs有两种写法,一种是处理当前访问的节点,如果是访问过的节点则终止本层递归;另一种是处理下一层访问的节点,这样不需要写终止条件。这道题不用回溯,因为只需要判断1节点是否能到达所有节点,就没有必要回溯去撤销操作,只要遍历过的节点一律标记上。

from collections import defaultdict
def dfs(graph,key,visited):
    #终止条件
    if visited[key]:
        return 
    visited[key] = True 
    for i in graph[key]:
        dfs(graph,i,visited)

#使用邻接表
n,k = map(int,input().split())
graph = defaultdict(list)
for _ in range(k):
    s,t = map(int,input().split())
    graph[s].append(t)
visited = [False] * (n+1) 
dfs(graph,1,visited)
#遍历
res = 1
for i in range(1,n+1):
    if not visited[i]:
        res = -1
print(res)
#没有终止条件
from collections import defaultdict
def dfs(graph,key,visited):
    for i in graph[key]:
        #如果没有被遍历过
        if not visited[i]:
            visited[i] = True
            dfs(graph,i,visited)
n,k = map(int,input().split())
graph = defaultdict(list)
for _ in range(k):
    s,t = map(int,input().split())
    graph[s].append(t)
visited = [False] * (n+1)
#初始化
visited[1] = True
dfs(graph,1,visited)
res = 1 
for i in range(1,n+1):
    if not visited[i]:
        res = -1
print(res)

3. 106. 岛屿的周长

题目链接:106. 岛屿的周长
文档讲解: 代码随想录

岛屿只有一个,那么当遇到grod[i][j] = 1时,那么就会进入搜索。当走不通时,周长加一。走不通有两种情况,一种是之前访问过,另一种是遇到水域,因此具体为当遇到水域的时候周长加一。同时,到边界也算走不通,也要加一。

direction = [[0,1],[0,-1],[1,0],[-1,0]]
count = 0
def dfs(grid,visited,x,y):
   global count
   for i,j in direction:
        next_x = x + i 
        next_y = y + j 
        if next_x < 0 or next_x >= len(grid) or next_y < 0 or next_y >= len(grid[0]):
            count += 1
            continue
        if grid[next_x][next_y] == 0:
            count += 1 
        if not visited[next_x][next_y] and grid[next_x][next_y] == 1:
            visited[next_x][next_y] = True 
            dfs(grid,visited,next_x,next_y)
n,m = map(int,input().split())
grid = []
for _ in range(n):
    grid.append(list(map(int,input().split())))
visited = [[False] * m for _ in range(n)]
count = 0
for i in range(n):
    for j in range(m):
        if not visited[i][j] and grid[i][j] == 1:
            visited[i][j] = True
            dfs(grid,visited,i,j)
print(count)

果然,我惯性思维了,这道题用不到dfs。有两种解法,一种是遍历每格,遇到岛屿就计算其上下左右的空格情况,如果遇到水域和出界则说明是一条边。

n,m = map(int,input().split())
grid = []
for _ in range(n):
    grid.append(list(map(int,input().split())))
direction = [[0,1],[0,-1],[1,0],[-1,0]]
res = 0
for i in range(n):
    for j in range(m):
        if grid[i][j] == 1:
            for a,b in direction:
                next_i = i + a 
                next_j = j + b 
                if next_i < 0 or next_i >= len(grid) or next_j < 0 or next_j >= len(grid[0]):
                    res += 1 
                    continue 
                if grid[next_i][next_j] == 0:
                    res += 1 
print(res)

另一种解法是,计算出总的岛屿数量,统计相邻的岛屿数量,total * 4 - near * 2。

n,m = map(int,input().split())
grid = []
for _ in range(n):
    grid.append(list(map(int,input().split())))
total = 0
near = 0 
for i in range(n):
    for j in range(m):
        if grid[i][j] == 1:
            total += 1 
            #为了防止重复,只统计上边和左边
            if i >= 1 and grid[i-1][j] == 1:
                near += 1 
            if j >= 1 and grid[i][j-1] == 1:
                near += 1 
res = total * 4 - near * 2 
print(res)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值