题目的链接在这里:https://leetcode-cn.com/problems/01-matrix/
题目大意
给定一个由 0 和 1 组成的矩阵 mat ,请输出一个大小相同的矩阵,其中每一个格子是 mat 中对应位置元素到最近的 0 的距离。两个相邻元素间的距离为 1 。
一、示意图
二、解题思路
动态规划BFS
动态规划
代码如下:
class Solution {
public int[][] updateMatrix(int[][] mat) {
//再输出一个矩阵 每一个格子是mat中对应元素到最近的0的距离
//重点就是怎么更新呢 如果一个位置是1 那就去判断他的四周的距离再加上1是吧 那前提是他的四周都更新过了呀
//所以就像我说的 需要先从右下到左上进行一次动态规划 然后再是左上到右下
int[][] result=new int[mat.length][mat[0].length];
//要对result进行初始值判断 初始值全是0
int xLength=mat.length;
int yLength=mat[0].length;
//然后先从右下到左上吧
for(int i=xLength-1;i>=0;i--){
for(int j=yLength-1;j>=0;j--){
//确实是需要初始化的
result[i][j]=10000;
//就是这个范围了
if(mat[i][j]==0){
//说明都不需要判断
//这里就需要进行操作了
result[i][j]=0;
continue;
}
else{
/**
* 不然的话 就需要进行动态规划了
* 这样的 右下到左上的运行轨迹是 从最右下的 先往左移 然后再一直左移 然后直到到最前一个 然后到上一层的最右边这样
* 所以原则上来说 他只能和当前的自己 不是和上一个做对比 而是需要和自己相邻的做对比 而和自己相邻的 并且以及被访问过的 只可能是 自己的右边 以及自己的下面 这些都可以进行访问的
* 如果是i等于 xLength-1 说明在最后一层 那只可能是在右边 而如果j在yLength-1 也就是说 他只可能在 下面 所以需要进行判断
* 判断方法就是 反向操作 既然不能等于这些 那就进行不等于这些的操作
*/
if(i<xLength-1){
//这个就说明 他一定是可以和下边的这个进行判断的
result[i][j]=Math.min(result[i][j],result[i+1][j]+1);
}
if(j<yLength-1){
//那就是说明 他也一定是可以和他 右边这个进行判断的
result[i][j]=Math.min(result[i][j],result[i][j+1]+1);
}
}
}
}
//这样右下到左上就完成了 然后第二次动态规划就是 左上到右下
for(int i=0;i<xLength;i++){
for(int j=0;j<yLength;j++){
//这个就不用初始化了 并且 这里移动方向就是从 左一直右移 然后到下一层的最左边
if(mat[i][j]==0){
//感觉像是多余操作
result[i][j]=0;
}
else{
/**
* 开始动态规划 一般来说 是可以和自己的左边 以及上边比的 但如果在第一行 就只能和左边比较 如果在第一列 就只能和自己的上边比较
*/
if(i>0){
//说明不在第一行 可以和自己的上边比较了
result[i][j]=Math.min(result[i][j],result[i-1][j]+1);
}
if(j>0){
//说明不在第一列 可以和自己的左边进行比较了
result[i][j]=Math.min(result[i][j],result[i][j-1]+1);
}
}
}
}
return result;
}
}
bfs
代码如下:
class Solution {
public int[][] updateMatrix(int[][] mat) {
//用BFS试试看
Queue<int[]> queue=new LinkedList<>();
//然后把其中的所有0的都进队列中
for(int i=0;i<mat.length;i++){
for(int j=0;j<mat[0].length;j++){
if(mat[i][j]==0){
queue.add(new int[]{i,j});
}
}
}
//然后是他的四个方位
int[][] pos={{0,1},{0,-1},{1,0},{-1,0}};
int[][] res=new int[mat.length][mat[0].length];
int step=0;
while (!queue.isEmpty()){
//先把第一波等于0的放进去
//也就是意味着 res默认值是0 而那些在第一波0边上的1 也全都是变成了距离为一 也就是从0开始扩散出去 每一次都进行扩散
step++;
int size=queue.size();
for(int i=0;i<size;i++){
//然后取出这几个
int[] poll = queue.poll();
//并进行更新
for(int j=0;j<4;j++){
int newX=poll[0]+pos[j][0];
int nexY=poll[1]+pos[j][1];
//然后进行判断 需要是合法的 并且是等于1 的
if(newX>=0&&newX<mat.length&&nexY>=0&&nexY<mat[0].length&&mat[newX][nexY]==1){
//说明这一波1是距离对应的0 最近的一批 也就是第一步的这些
res[newX][nexY]=step;
//然后为了防止他们 再次被访问到 设置成0
mat[newX][nexY]=0;
//并把数值 放到队列当中
queue.add(new int[]{newX,nexY});
}
}
}
}
return res;
}
}