📜  门| Sudo GATE 2021 测验 |第 34 题(1)

📅  最后修改于: 2023-12-03 15:42:20.394000             🧑  作者: Mango

门 | Sudo GATE 2021 测验 |第 34 题

本题考察迭代算法。题目描述如下:

给定一个M*N的01矩阵,每个位置要么是0要么是1。现在定义一个操作,将一个0变成1并将与它相邻的1改为0。问最少需要执行多少次操作才能使整个矩阵中的全部0变为1。

例如,对于下面的4*4矩阵:

1 0 0 1 
0 0 1 0
0 0 0 0
1 0 0 1

最少需要执行3次操作才能使全部0变成1。一种可行的方案如下(第1次操作将右上角的0变为了1,第2次操作将右下角的0变为了1,第3次操作将左下角的0变为了1):

1 1 1 1
0 0 0 0
0 0 0 0
1 1 1 1

请实现以下函数:

    def min_ops(matrix: List[List[int]]) -> int:
        pass

函数参数是一个M*N的01矩阵;函数返回值是最少需要执行多少次操作才能使整个矩阵中的全部0变为1。

算法思路

使用迭代算法求解。每一次从矩阵中找到一个0,并将它与相邻的1一起修改。修改的过程可以采用DFS或BFS。

我们可以构建一个队列,将每一次操作的结果放入队列。如果队列中存在所有元素都是1的矩阵,则说明操作结束。

具体步骤如下:

  1. 遍历矩阵,如果遇到0,将它的坐标加入一个列表中。
  2. 对于列表中的每个坐标,分别进行以下操作: a. 将该坐标的值设为1; b. 遍历与该坐标相邻的四个位置(左、右、上、下),如果该位置的值为1,则将其设为0;
  3. 将修改后的矩阵加入队列;
  4. 重复步骤2和3,直至队列中存在所有元素都是1的矩阵;
  5. 返回队列长度-1。
代码实现
from typing import List

def min_ops(matrix: List[List[int]]) -> int:
    # 构造四联通坐标偏移数组
    directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]
    m, n = len(matrix), len(matrix[0])
    queue = []

    def bfs(matrix: List[List[int]]) -> List[List[int]]:
        for i in range(m):
            for j in range(n):
                if matrix[i][j] == 0:
                    # 将0元素的坐标加入列表中
                    queue.append((i, j))

        step = 0
        while queue:
            # 记录队列长度,即本轮需要修改的元素个数
            size = len(queue)
            # 本轮修改的元素个数加入step
            step += 1
            for i in range(size):
                x, y = queue.pop(0)
                matrix[x][y] = 1
                # 四联通判断
                for dx, dy in directions:
                    nx, ny = x + dx, y + dy
                    if 0 <= nx < m and 0 <= ny < n and matrix[nx][ny] == 1:
                        matrix[nx][ny] = 0
                        queue.append((nx, ny))

            # 如果此时矩阵内全是1,则返回step
            if all(all(row) for row in matrix):
                return step

        return -1

    return bfs(matrix)
复杂度分析

由于每个元素只会被修改一次,因此时间复杂度为$O(mn)$,其中m和n分别为矩阵的行数和列数。

空间复杂度为$O(mn)$,其中m和n分别为矩阵的行数和列数,主要是存储列表和队列所占用的空间。