第十一章 图论 Part4

任务

127. 单词接龙

字典 wordList 中从单词 beginWord 到 endWord 的 转换序列 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> ... -> sk:

  • 每一对相邻的单词只差一个字母。
  • 对于 1 <= i <= k 时,每个 si 都在 wordList 中。注意, beginWord 不需要在 wordList 中。
  • sk == endWord

给你两个单词 beginWord 和 endWord 和一个字典 wordList ,返回 从 beginWord 到 endWord 的 最短转换序列 中的 单词数目 。如果不存在这样的转换序列,返回 0

思路

由于是求最短路径,实际转化为通过bfs第一次遍历到endWord的情况。bfs的逻辑与二叉树层序遍历的逻辑相似,可以参考二叉树层序遍历的逻辑。
题目中的单词数目或者说路径长度可以理解为遍历的层数(bfs),只不过初始为1

class Solution:
    def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int:
        if endWord not in wordList:
            return 0
        wordSet = set(wordList)
        que = deque()
        que.append(beginWord)
        pathLength = 1
        while que: # 处理所有节点
            for _ in range(len(que)): # 处理每层全部节点
                curWord = que.popleft()
                
                for i in range(len(curWord)):
                    newWord  = curWord
                    for j in range(26):
                        character=  chr(ord('a') + j)
                        newWord = newWord[:i] + character + newWord[i+1:]
                        
                        if newWord == endWord:
                            return pathLength+1

                        if newWord in wordSet:
                            wordSet.remove(newWord)
                            que.append(newWord)
            pathLength += 1
        return 0

Kama105.有向图的完全可达性

给定一个有向图,包含 N 个节点,节点编号分别为 1,2,...,N。现从 1 号节点开始,如果可以从 1 号节点的边可以到达任何节点,则输出 1,否则输出 -1。

思路

由于是有向图,实际上就是dfs的应用,需要注意的是有很多种写法如

  • 终止条件写外面,处理当前节点. (这种写法一般在求两点间所有路径的编码中出现,终止条件是当前点等于终点时,统计一条路径并返回,而在循环中有回溯的逻辑,写在外面是因为符合思维习惯)
  • 终止条件隐藏在遍历的过程中,处理下一个访问的节点 (个人很少用这种写法)
  • 终止条件隐藏在遍历过程中,处理当前节点(当前写法),类比之前输入为grid时的写法,只不过输入改成了邻接表(这种写法在grid中使用是因为比如岛屿问题,水流问题中,都是一定条件的情况下,才遍历格子,记录在visited中,这个条件写在循环中比较符合思维习惯,而不是用否条件(不遍历格子的条件)写在外面的终止条件里)

只要熟练掌握其中一种写法,其他写法可以理解即可。

def dfs(graph, key, visited):
    visited[key] = true; # 能到达的点标记为true
    for neibokey in graph[key]:
        if (visited[neibokey] == false): # 递归遍历没访问过的节点
            dfs(graph, neibokey, visited)    
    
def canArrive(graph):
    visited = [[false] *len(graph[0]) for _ in range(graph)]
    dfs(graph,1,visited) # dfs遍历并标记走过的节点
    for i in range(len(visited)):
        if not visited[i]:
            return False
    return True

463. 岛屿的周长

给定一个 row x col 的二维网格地图 grid ,其中:grid[i][j] = 1 表示陆地, grid[i][j] = 0 表示水域。

网格中的格子 水平和垂直 方向相连(对角线方向不相连)。整个网格被水完全包围,但其中恰好有一个岛屿(或者说,一个或多个表示陆地的格子相连组成的岛屿)。

岛屿中没有“湖”(“湖” 指水域在岛屿内部且不和岛屿周围的水相连)。格子是边长为 1 的正方形。网格为长方形,且宽度和高度均不超过 100 。计算这个岛屿的周长。

思路

容易用惯性思维只要看到岛屿就要去遍历,实际上这道题求的是周长,不需要遍历,直观的,只要求岛屿的交接处是水域或者是边界的个数即可。

class Solution:
    def islandPerimeter(self, grid: List[List[int]]) -> int:
        
        dir = [(1,0),(0,1),(-1,0),(0,-1)] #逆时针四个方向
        res = 0
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if(grid[i][j] == 1):
                    for k in range(4):
                        x = i + dir[k][0]
                        y = j + dir[k][1]
                        if x < 0 or y<0 or x>=len(grid) or y>=len(grid[0]) or grid[x][y] == 0:#坐标在边界上: 或者坐标位置是水
                            res += 1
        return res
posted @ 2024-09-07 12:21  haohaoscnblogs  阅读(16)  评论(0)    收藏  举报