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]]
头一次打算完完整整不看题解自己写完,但是高估了自己,写了好久好久,实在搞不出来就找别人的代码看。要注意边界,否则就会调好久好久好久。话说为什么用c++不行,改成Java就行了呢,难搞。
代码:
class Solution {
//深度优先搜索
int dx[]={1,0,0,-1};
int dy[]={0,1,-1,0};
void dfs(int[][] mat,int x,int y){//[x][y]已知,求[x][y]四个方向的值
int m=mat.length,n=mat[0].length;
for(int i=0;i<4;i++){
int mx = x+dx[i],my = y+dy[i];
if(mx>=0&&mx<m&&my>=0&&my<n&&mat[mx][my]>mat[x][y]+1){
mat[mx][my] = mat[x][y] +1;
dfs(mat,mx,my);
}
}
}
boolean Zeronear(int[][] mat,int x,int y){//四个方向有没有0
int m=mat.length,n=mat[0].length;
for(int i=0;i<4;i++){
int nextx=x+dx[i],nexty=y+dy[i];
if(nextx>=0&&nexty>=0&&nextx<m&&nexty<n&&mat[nextx][nexty]==0) //在矩阵内且值为0
return true;
}
return false;
}
public int[][] updateMatrix(int[][] mat) {
int m=mat.length;
if(m==0) return mat;
int n=mat[0].length;
//初始化mat矩阵,把值为1且四方无0的位置赋值为无穷大,可以用较大的数代替
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(Zeronear(mat,i,j)==false&&mat[i][j]==1)//该元素=1,且四个方向没有0
mat[i][j]=Integer.MAX_VALUE;
}
}
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(mat[i][j]==1)//该元素=1,从等于1的元素开始,向内递归
{dfs(mat,i,j);}
}
}
return mat;
}
};
994. 腐烂的橘子
在给定的 m x n 网格 grid 中,每个单元格可以有以下三个值之一:
值 0 代表空单元格;
值 1 代表新鲜橘子;
值 2 代表腐烂的橘子。
每分钟,腐烂的橘子 周围 4 个方向上相邻 的新鲜橘子都会腐烂。
返回 直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 -1 。
示例 1:
输入:grid = [[2,1,1],[1,1,0],[0,1,1]]
输出:4
示例 2:
输入:grid = [[2,1,1],[0,1,1],[1,0,1]]
输出:-1
解释:左下角的橘子(第 2 行, 第 0 列)永远不会腐烂,因为腐烂只会发生在 4 个正向上。
示例 3:
输入:grid = [[0,2]]
输出:0
解释:因为 0 分钟时已经没有新鲜橘子了,所以答案就是 0 。
代码:
class Solution {//广度优先搜索
public:
int orangesRotting(vector<vector<int>>& grid) {
int m=grid.size(),n=grid[0].size();
int dx[4]={1,0,0,-1},dy[4]={0,1,-1,0};
int fresh=0;//新鲜橘子数
queue<int>q;
for(int i=0;i<m;i++){//遍历,记录新鲜橘子数,将烂橘子加入队列
for(int j=0;j<n;j++){
//是2的话就记录该坐标是坏橘子,这里采用二维转一维,行数*总列数+列数——把矩阵铺开成一条线时对应的下标
if(grid[i][j]==2) q.push(i*n+j);
else if(grid[i][j]==1)fresh++;
}
}
if(!fresh) return 0;//没有新鲜橘子
int res=-1;
while(!q.empty()){//只要有腐烂橘子
int badSum=q.size();//当前轮次(对应层序遍历的一层)所含有多少个坏橘子
while(badSum){
int temp=q.front();//当前去感染其他橘子的烂橘子
q.pop();
int row=temp/n;//坐标还原
int col=temp%n;//坐标还原
for(int k=0;k<4;k++){//去感染四周
int newRow=row+dx[k];
int newCol=col+dy[k];
//被感染的两个条件 1.没有越界 2.有橘子且是新鲜橘子
if(newRow>=0&&newRow<m&&newCol>=0&&newCol<n&&grid[newRow][newCol]==1){
grid[newRow][newCol]=2;//标记感染过了
q.push(newRow*n+newCol);//下一轮就到这个坏橘去感染别橘
fresh--;
}
}
badSum--;
}
res++;//一轮结束就+1
}
//感染完还有新鲜橘子剩的话,那个橘子是隔离橘,感染不到它的,按题意返回-1
return fresh==0?res:-1;
}
};