leetcode(14)DFS系列题目

200. 岛屿数量

class Solution:
    def numIslands(self, grid: List[List[str]]) -> int:
        def dfs(grid, i, j):
            if not 0 <= i < len(grid) or not 0 <= j < len(grid[0]) or grid[i][j] == '0':
                return
            grid[i][j] = '0'
            dfs(grid, i + 1, j)
            dfs(grid, i - 1, j)
            dfs(grid, i, j - 1)
            dfs(grid, i, j + 1)
        count = 0
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if grid[i][j] == '1':
                    dfs(grid, i, j)
                    count += 1
        return count

695. 岛屿的最大面积

class Solution:
    def maxAreaOfIsland(self, grid: List[List[int]]) -> int:
        def dfs(grid, i, j):
            # 遇到边界或者遇到0了,就停止
            if not 0 <= i < len(grid) or not 0 <= j <len(grid[0]) or grid[i][j] == 0:
                return
            grid[i][j] = 0
            self.res += 1
            dfs(grid, i - 1, j)
            dfs(grid, i + 1, j)
            dfs(grid, i, j - 1)
            dfs(grid, i, j + 1)
            return self.res
        maxS = 0
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if grid[i][j] == 1:
                    # 每个岛屿重新计算面积
                    self.res = 0
                    dfs(grid, i, j)
                    maxS = max(maxS, self.res)
        return maxS

934. 最短的桥

先通过 DFS 将其中一个岛屿的所有点找出来,放到一个队列 q 中。然后通过 BFS 一层层向外扩展,直至碰到另一个岛屿,此时将当前扩展的层数作为答案返回即可。
在 DFS 和 BFS 搜索的过程中,我们直接将已经访问过的点标记为 2,这样就不会重复访问。

class Solution:
    def shortestBridge(self, grid: List[List[int]]) -> int:
        def dfs(i, j):
            q.append((i, j))
            grid[i][j] = 2
            for a, b in pairwise(dirs):
                x = i + a
                y = j + b 
                if 0 <= x < n and 0 <= y < n and grid[x][y] == 1:
                    dfs(x, y)
        
        n = len(grid)
        dirs = (-1, 0, 1, 0, -1)
        q = deque()
        i, j = next((i, j) for i in range(n) for j in range(n) if grid[i][j])
        dfs(i, j)
        res = 0
        while 1:
            for _ in range(len(q)):  # 注意是q的层数
                i, j = q.popleft()  # 注意是弹出左边的
                for a, b in pairwise(dirs):
                    x = i + a
                    y = j + b 
                    if 0 <= x < n and 0 <= y < n:
                        if grid[x][y] == 1:
                            return res
                        elif grid[x][y] == 0:
                            grid[x][y] = 2
                            q.append((x, y))
            res += 1

79. 单词搜索

class Solution:
    def exist(self, board: List[List[str]], word: str) -> bool:
        dire = [(0,-1),(0,1),(1,0),(-1,0)]
        def dfs(i, j, k):
            if board[i][j] != word[k]:
                return False
            if k == len(word) - 1:
                return True
            visited.add((i, j))
            for x, y in dire:
                newi, newj = i + x, j + y
                if 0 <= newi < col and 0 <= newj < row:
                    if (newi, newj) not in visited:
                        if dfs(newi, newj, k + 1):
                            return True
            visited.remove((i, j))
            return False
        visited = set()
        col, row = len(board), len(board[0])            
        for i in range(col):
            for j in range(row):
                if dfs(i, j, 0):   
                    return True
        return False          

808. 分汤

记忆化搜索
由于每次操作都是 25 的倍数,因此,我们可以将每 25ml 的汤视为一份。这样就能将数据规模缩小到$ \left \lceil \frac{n}{25} \right \rceil$

class Solution:
    def soupServings(self, n: int) -> float:
        n = (n + 24) // 25
        if n >= 179:
            return 1.0
        @cache
        def dfs(i, j):
            if i <= 0 and j <= 0:
                return 0.5
            if i <= 0:
                return 1
            if j <= 0:
                return 0
            return 0.25 * (dfs(i - 4, j) + dfs(i - 3, j - 1) +  
            dfs(i - 2, j - 2) + dfs(i - 1, j - 3))
        return dfs(n, n)

6255. 两个城市间路径的最小分数

反正跟节点1连接的所有节点都能到达n,就直接遍历从节点1发散下去的所有路径,并记录在res里

class Solution:
    def minScore(self, n: int, roads: List[List[int]]) -> int:
        g = [[] for _ in range(n + 1)]
        for a, b, d in roads:
            g[a].append((b, d))
            g[b].append((a, d))
        # print(g)
        q = g[1]
        vis = set()
        vis.add(1)
        res = []
        for x, v in g[1]:
            res.append(v)
        while q:
            x, v = q.pop()
            for y, d in g[x]:
                if y not in vis:
                    q.append((y, d))
                    vis.add(x)
                    res.append(d)
                
        return min(res)

posted @ 2022-05-16 13:34  YTT77  阅读(30)  评论(0编辑  收藏  举报