LeetCode日常刷题542、

542. 01 矩阵

给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离。

两个相邻元素间的距离为 1 。

示例 1:
输入:

0 0 0
0 1 0
0 0 0

输出:

0 0 0
0 1 0
0 0 0

示例 2:
输入:

0 0 0
0 1 0
1 1 1

输出:

0 0 0
0 1 0
1 2 1

注意:

  1. 给定矩阵的元素个数不超过 10000。
  2. 给定矩阵中至少有一个元素是 0。
  3. 矩阵中的元素只在四个方向上相邻: 上、下、左、右。

这道题应用的是广度优先搜索(BFS算法),是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。

BFS算法,一般是用队列实现,先进先出。其主要原理是,使用队列保存未被查询过的结点。

最简单的例子就是:我们丢了东西,首先会在自己的周围找,如果周围没找到,那么就会想远一点的地方,然后去找。

下面是BFS算法的常用模块:

BFS:
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn=100;
bool vst[maxn][maxn]; // 访问标记
int dir[4][2]={0,1,0,-1,1,0,-1,0}; // 方向向量

struct State // BFS 队列中的状态数据结构
{
int x,y; // 坐标位置
int Step_Counter; // 搜索步数统计器
};

State a[maxn];

bool CheckState(State s) // 约束条件检验
{
if(!vst[s.x][s.y] && ...) // 满足条件
return 1;
else // 约束条件冲突
return 0;
}

void bfs(State st)
{
queue <State> q; // BFS 队列
State now,next; // 定义2 个状态,当前和下一个
st.Step_Counter=0; // 计数器清零
q.push(st); // 入队
vst[st.x][st.y]=1; // 访问标记
while(!q.empty())
{
now=q.front(); // 取队首元素进行扩展
if(now==G) // 出现目标态,此时为Step_Counter 的最小值,可以退出即可
{
...... // 做相关处理
return;
}
for(int i=0;i<4;i++)
{
next.x=now.x+dir[i][0]; // 按照规则生成下一个状态
next.y=now.y+dir[i][1];
next.Step_Counter=now.Step_Counter+1; // 计数器加1
if(CheckState(next)) // 如果状态满足约束条件则入队
{
q.push(next);
vst[next.x][next.y]=1; //访问标记
}
}
q.pop(); // 队首元素出队
}
 return;
}

int main()
{
......
 return 0;
}

对于此题,我们用java来写。我们分析道,题目要求必须含有零,那么我们可以把所有0入队,把1置为MAX_VALUE,然后把最靠近0的1的距离算出来,然后将他们入队,再算距离最靠近0的1的1的距离算出来,依次处理

class Solution {
    public List<List<Integer>> updateMatrix(List<List<Integer>> matrix) {  
        if (matrix == null || matrix.size() == 0)  
            return matrix;  
        int m = matrix.size();  
        int n = matrix.get(0).size();  
        Queue<int[]> q = new LinkedList<>();  
        for (int i = 0; i < m; i++)  
            for (int j = 0; j < n; j++) {  
                // 把0元素加入队列中,以备波及影响周围元素  
                if (matrix.get(i).get(j) == 0)  
                    q.offer(new int[] { i, j });  
                else  
                    // 设为最大值,方便求0元素影响值  
                    matrix.get(i).set(j, Integer.MAX_VALUE);  
            }  
        // 上下左右  
        int[][] dirs = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };  
        while (!q.isEmpty()) {  
            int cell[] = q.poll();  
            for (int[] d : dirs) {  
                int row = cell[0] + d[0];  
                int col = cell[1] + d[1];  
                if (row < 0 || row >= m || col < 0 || col >= n)  
                    continue;  
                // 上下左右取到的值  
                int value = matrix.get(row).get(col);  
                int tmp = matrix.get(cell[0]).get(cell[1]) + 1;  
                // 如果value小,那说明之前已经更新过,不是max  
                if (value <= tmp)  
                    continue;  
                q.offer(new int[] { row, col });  
                matrix.get(row).set(col, tmp);  
      
            }  
      
        }  
      
        return matrix;  
    }  
}

def updateMatrix(self, matrix):
    if not matrix or not matrix[0]: return matrix
    M, N = len(matrix), len(matrix[0])
     
    cur = set()
    for i in range(M):
        for j in range(N):
            if matrix[i][j] == 1:
                for ni, nj in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
                    if -1 < ni < M and -1 < nj < N and matrix[ni][nj] == 0:
                        cur.add((i, j))
                        matrix[i][j] = -1
                        break
    distance = 1
    while cur:
        nxt = set()
        distance += 1
        for i, j in cur:
            for ni, nj in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
                if -1 < ni < M and -1 < nj < N and matrix[ni][nj] == 1:
                    matrix[ni][nj] = distance
                    nxt.add((ni, nj))
        cur = nxt
     
    for i in range(M):
        for j in range(N):
            if matrix[i][j] == -1:
                matrix[i][j] = 1
     
    return matrix


猜你喜欢

转载自blog.csdn.net/zhang_yixuan_ss/article/details/80242707
今日推荐