深度优先搜索(DFS)和广度优先搜索(BFS)算法题整合(持更)

深度优先搜索的思想可以参考大佬的博客。
广度优先搜索的思想可以参考这位大佬的博客。

  1. 【扫雷游戏】题目地址
    给定一个代表游戏板的二维字符矩阵。 ‘M’ 代表一个未挖出的地雷,‘E’ 代表一个未挖出的空方块,‘B’ 代表没有相邻(上,下,左,右,和所有4个对角线)地雷的已挖出的空白方块,数字(‘1’ 到 ‘8’)表示有多少地雷与这块已挖出的方块相邻,‘X’ 则表示一个已挖出的地雷。
    现在给出在所有未挖出的方块中(‘M’或者’E’)的下一个点击位置(行和列索引),根据以下规则,返回相应位置被点击后对应的面板:
    如果一个地雷(‘M’)被挖出,游戏就结束了- 把它改为 ‘X’。
    如果一个没有相邻地雷的空方块(‘E’)被挖出,修改它为(‘B’),并且所有和其相邻的未挖出方块都应该被递归地揭露。
    如果一个至少与一个地雷相邻的空方块(‘E’)被挖出,修改它为数字(‘1’到’8’),表示相邻地雷的数量。
    如果在此次点击中,若无更多方块可被揭露,则返回面板。

思路:有3条规则需要明确:规则1,点击的位置如果是地雷’M’,则将它改为’X’,游戏结束,直接返回。
如果点击的是空方块’E’,则计算其八个方向是否有地雷,(1)若有,规则2,对应修改为数字(‘1’到‘8’),(2)若无,规则3,当前格子修改为’B’,同时向’B’的周围(八个方向)开始扩展,遍历到的格子必须是未被挖出的空方块’E’。
注意:当前格子为’B’时,才向周围搜索,如果当前格子为数字,是不向周围搜索的。
时间复杂度: O ( n m ) O(nm) O(nm) n m nm nm是整个二维字符矩阵的方块数,最差的情况就是每个方块遍历一遍。

class Solution:
    directions = ((-1,0),(1,0),(0,-1),(0,1),(-1,-1),(-1,1),(1,-1),(1,1))
    def updateBoard(self, board: List[List[str]], click: List[int]) -> List[List[str]]:
        i = click[0]
        j = click[1]
        # 规则1,当点到的格子有雷时,直接将'M'替换成'X'
        if board[i][j] == 'M':
            board[i][j] = 'X'
        elif board[i][j] == 'E':
            Solution.dfs(board,i,j)
        return board
        # 当点到的格子是空方块'E',需要判断周围有无雷,有雷填数字,无雷填'B'
    def dfs(board,i,j):
        cnt = 0 #初始化雷的个数为0
        for ni,nj in Solution.directions:
            ni, nj = ni+i, nj+j
            # 如果当前格子的相邻格子不存在,即下标越界了,则跳过,执行下一循环
            if ni<0 or ni>=len(board) or nj<0 or nj>=len(board[0]):
                continue
            if board[ni][nj] == 'M':
                cnt += 1
        # 规则2,如果当前格子周围有雷,则填写数字
        if cnt>0:
            board[i][j] = str(cnt)
        # 规则3,如果当前格子周围无雷,则填写'B'
        else:
            board[i][j] = 'B'
            # 现在需要向'B'周围扩展,能够被扩展的条件是该格子必须为未挖出的空方块'E',该格子上有其他标志说明已经被扩展过了
            for ni,nj in Solution.directions:
                ni, nj = ni+i, nj+j
                if ni<0 or ni>=len(board) or nj<0 or nj>=len(board[0]) or board[ni][nj]!='E':
                    continue
                Solution.dfs(board,ni,nj)
  1. 【钥匙和房间】题目地址
    有 N 个房间,开始时你位于 0 号房间。每个房间有不同的号码:0,1,2,…,N-1,并且房间里可能有一些钥匙能使你进入下一个房间。
    在形式上,对于每个房间 i 都有一个钥匙列表 rooms[i],每个钥匙 rooms[i][j] 由 [0,1,…,N-1] 中的一个整数表示,其中 N = rooms.length。 钥匙 rooms[i][j] = v 可以打开编号为 v 的房间。
    最初,除 0 号房间外的其余所有房间都被锁住。
    你可以自由地在房间之间来回走动。
    如果能进入每个房间返回 true,否则返回 false。
    示例 1:
    输入: [[1],[2],[3],[]]
    输出: true
    解释:
    我们从 0 号房间开始,拿到钥匙 1。
    之后我们去 1 号房间,拿到钥匙 2。
    然后我们去 2 号房间,拿到钥匙 3。
    最后我们去了 3 号房间。
    由于我们能够进入每个房间,我们返回 true。
    示例 2:
    输入:[[1,3],[3,0,1],[2],[0]]
    输出:false
    解释:我们不能进入 2 号房间。
    提示:
    1 <= rooms.length <= 1000
    0 <= rooms[i].length <= 1000
    所有房间中的钥匙数量总计不超过 3000。
    【深度优先搜索】C语言
//num为能打开的房间个数,若所有房间能被开锁,则num的大小应为房间个数
int num;

void dfs(int** rooms, int* roomsColSize, int* vis, int x){
    vis[x] = true;
    num++;
    for(int i=0;i<roomsColSize[x];i++){
        if(!vis[rooms[x][i]]){
            dfs(rooms,roomsColSize,vis,rooms[x][i]);
        }
    }

}

//roomsColSize存储的是每列的尺寸
bool canVisitAllRooms(int** rooms, int roomsSize, int* roomsColSize){
    int vis[roomsSize];
    memset(vis,0,sizeof(vis));
    num = 0;
    dfs(rooms,roomsColSize,vis,0);

    return num==roomsSize;
}

【深度优秀搜索】Python

class Solution:
    def canVisitAllRooms(self, rooms: List[List[int]]) -> bool:
        def dfs(x: int):
            vis.add(x)
            nonlocal num
            num += 1
            for it in rooms[x]:
                if it not in vis:
                    dfs(it)

        vis = set()
        num = 0
        dfs(0)
        n = len(rooms)
        return num==n

【广度优先搜索】C语言

bool canVisitAllRooms(int** rooms, int roomsSize, int* roomsColSize) {
    int vis[roomsSize], que[roomsSize];
    memset(vis, 0, sizeof(vis));
    int left = 0, right = 1, num = 0;
    vis[0] = true;
    que[0] = 0;
    while (left < right) {
        int x = que[left++];
        num++;
        for (int i = 0; i < roomsColSize[x]; i++) {
            if (!vis[rooms[x][i]]) {
                vis[rooms[x][i]] = true;
                que[right++] = rooms[x][i];
            }
        }
    }
    return num == roomsSize;
}

【广度优先搜索】Python

class Solution:
    def canVisitAllRooms(self, rooms: List[List[int]]) -> bool:
        n = len(rooms)
        num = 0
        vis = {0}
        que = collections.deque([0])

        while que:
            x = que.popleft()
            num += 1
            for it in rooms[x]:
                if it not in vis:
                    vis.add(it)
                    que.append(it)
        
        return num == n

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/keys-and-rooms/solution/yao-chi-he-fang-jian-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

你可能感兴趣的:(算法)