LeetCode 542. 01 矩阵 C

542. 01 矩阵

给定一个由 0 和 1 组成的矩阵 mat ,请输出一个大小相同的矩阵,其中每一个格子是 mat 中对应位置元素到最近的 0 的距离。

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

示例 1:
在这里插入图片描述
输入:mat = [[0,0,0],[0,1,0],[0,0,0]]
输出:[[0,0,0],[0,1,0],[0,0,0]]

示例 2:
在这里插入图片描述

输入:mat = [[0,0,0],[0,1,0],[1,1,1]]
输出:[[0,0,0],[0,1,0],[1,2,1]]

提示:

m == mat.length
n == mat[i].length
1 <= m, n <= 104
1 <= m * n <= 104
mat[i][j] is either 0 or 1.
mat 中至少有一个 0


解题:

这道题目有两种解题思路:
1、BFS(广度优先搜索)
2、DP(动态规划)
这里首先展示第一种做法——广度优先搜索

广度优先搜索关键在于额外拥有一个队列用于存储结点的坐标,步骤如下:
1、首先将所有值为 0 的点存入队列,用于首先进行搜索,并用一个额外的数组标记为已访问
2、每搜索到一个点,就记该结点的步长为 0 到前一个结点的最短步长 + 1,并标记为已访问

(○´・д・)ノ 需要注意的是,这里不用考虑如果有多个 0 都到达这个位置,是否需要取步长的最小值。因为每个结点我们只搜索它上下左右四个点,广度优先搜索保证了首先将距离该轮所有结点步长为 1 的点全部搜索完毕后才会继续搜索下一轮结点。

代码如下:

const int dx[4] = {0, 0,-1, 1};
const int dy[4] = {1,-1, 0, 0};

int n, m;

int** updateMatrix(int** mat, int matSize, int* matColSize, int* returnSize, int** returnColumnSizes){
    n = matSize, m = matColSize[0];
    *returnSize = n;
    *returnColumnSizes = malloc(sizeof(int*)*n);
	int** isvisit = (int**)malloc(sizeof(int*)*n);
	for(int i = 0; i < n; i++){
		isvisit[i] = (int*)calloc(m, sizeof(int));
        (*returnColumnSizes)[i] = m;
	}
	int** queue = (int**)malloc(sizeof(int*)*m*n);
	int x = 0;	// 用于跟随队列
	// 首先在队列中放入所有 0 的位置
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            if(mat[i][j] == 0){
            	queue[x] = (int*)malloc(sizeof(int)*2);
                queue[x][0] = i, queue[x++][1] = j;
                isvisit[i][j] = 1;	// 标记为已访问
            }
        }
    }
    int loc = 0;	// 记录此时已经取到的位置,取过的点将不再访问
    while(loc < x){
    	int i = queue[loc][0], j = queue[loc++][1];	// 相当于队列poll()的作用
    	for(int d = 0; d < 4; d++){	// 遍历上下左右四个方向
    		int new_x = i + dx[d], new_y = j + dy[d];
    		if(new_x >= 0 && new_x < n && new_y >= 0 && new_y < m && !isvisit[new_x][new_y]){
    			mat[new_x][new_y] = mat[i][j] + 1;	// 直接在原指针上操作,当前步长 = 前一步长 + 1
                queue[x] = (int*)malloc(sizeof(int)*2);
    			queue[x][0] = new_x, queue[x++][1] = new_y;	// 用于下一轮的处理
    			isvisit[new_x][new_y] = 1;	// 标记为已访问
			}
		}
	}
    return mat;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值