542. 01 Matrix(深搜/广搜/DP的题目)
来源:互联网 发布:淘宝拒收怎么申请退款 编辑:程序博客网 时间:2024/05/20 22:29
Given a matrix consists of 0 and 1, find the distance of the nearest 0 for each cell.
The distance between two adjacent cells is 1.Example 1:
Input:
0 0 00 1 00 0 0Output:
0 0 00 1 00 0 0
Example 2:
Input:
0 0 00 1 01 1 1Output:
0 0 00 1 01 2 1
Note:
- The number of elements of the given matrix will not exceed 10,000.
- There are at least one 0 in the given matrix.
- The cells are adjacent in only four directions: up, down, left and right.
Approach #1 Brute force [Time Limit Exceeded]
Intuition
Do what the question says.
Algorithm
- Initialize
dist[i][j]=INT_MAX
for all{i,j}
cells. - Iterate over the matrix.
- If cell is
0
,dist[i][j]=0
, - Else, for each
1
cell,- Iterate over the entire matrix
- If the cell is
0
, calculate its distance from current cell asabs(k-i)+abs(l-j)
. - If the distance is smaller than the current distance, update it.
C++
vector<vector<int> > updateMatrix(vector<vector<int> >& matrix){ int rows = matrix.size(); if (rows == 0) return matrix; int cols = matrix[0].size(); vector<vector<int> > dist(rows, vector<int>(cols, INT_MAX)); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { if (matrix[i][j] == 0) dist[i][j] = 0; else { for (int k = 0; k < rows; k++) for (int l = 0; l < cols; l++) if (matrix[k][l] == 0) { int dist_01 = abs(k - i) + abs(l - j); dist[i][j] = min(dist[i][j], abs(k - i) + abs(l - j)); } } } } return dist;}
Complexity Analysis
Time complexity: O((r⋅c)2). Iterating over the entire matrix for each
1
in the matrix.Space complexity: O(r⋅c). No extra space required than the
vector<vector<int> > dist
Approach #2 Using BFS [Accepted]
Intuition
A better brute force: Looking over the entire matrix appears wasteful and hence, we can use Breadth First Search(BFS) to limit the search to the nearest 0
found for each 1
. As soon as a 0
appears during the BFS, we know that the 0
is nearest, and hence, we move to the next 1
.
Think again: But, in this approach, we will only be able to update the distance of one 1
using one BFS, which could in fact, result in slightly higher complexity than the Approach #1 brute force. But hey,this could be optimised if we start the BFS from 0
s and thereby, updating the distances of all the 1
s in the path.
Algorithm
- For our BFS routine, we keep a queue,
q
to maintain the queue of cells to be examined next. - We start by adding all the cells with
0
s toq
. - Intially, distance for each
0
cell is0
and distance for each1
isINT_MAX
, which is updated during the BFS. - Pop the cell from queue, and examine its neighbours. If the new calculated distance for neighbour
{i,j}
is smaller, we add{i,j}
toq
and updatedist[i][j]
.
C++
vector<vector<int> > updateMatrix(vector<vector<int> >& matrix){ int rows = matrix.size(); if (rows == 0) return matrix; int cols = matrix[0].size(); vector<vector<int> > dist(rows, vector<int>(cols, INT_MAX)); queue<pair<int, int> > q; for (int i = 0; i < rows; i++) for (int j = 0; j < cols; j++) if (matrix[i][j] == 0) { dist[i][j] = 0; q.push({ i, j }); //Put all 0s in the queue. } int dir[4][2] = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } }; while (!q.empty()) { pair<int, int> curr = q.front(); q.pop(); for (int i = 0; i < 4; i++) { int new_r = curr.first + dir[i][0], new_c = curr.second + dir[i][1]; if (new_r >= 0 && new_c >= 0 && new_r < rows && new_c < cols) { if (dist[new_r][new_c] > dist[curr.first][curr.second] + 1) { dist[new_r][new_c] = dist[curr.first][curr.second] + 1; q.push({ new_r, new_c }); } } } } return dist;}
Complexity analysis
- Time complexity: O(r⋅c).
Since, the new cells are added to the queue only if their current distance is greater than the calculated distance, cells are not likely to be added multiple times.
Space complexity: O(r⋅c). Additional O(r⋅c) for queue than in Approach #1
Approach #3 DP Approach [Accepted]
Intuition
The distance of a cell from 0
can be calculated if we know the nearest distance for all the neighbours, in which case the distance is minimum distance of any neightbour + 1. And, instantly, the word come to mind DP!!
For each 1
, the minimum path to 0
can be in any direction. So, we need to check all the 4 direction. In one iteration from top to bottom, we can check left and top directions, and we need another iteration from bottom to top to check for right and bottom direction.
Algorithm
- Iterate the matrix from top to bottom-left to right:
- Update dist[i][j]=min(dist[i][j],min(dist[i][j−1],dist[i−1][j])+1) i.e., minimum of the current dist and distance from top or left neighbour +1, that would have been already calculated previously in the current iteration.
- Now, we need to do the back iteration in the similar manner: from bottom to top-right to left:
- Update dist[i][j]=min(dist[i][j],min(dist[i][j+1],dist[i+1][j])+1) i.e. minimum of current dist and distances calculated from bottom and right neighbours, that would be already available in current iteration.
C++
vector<vector<int> > updateMatrix(vector<vector<int> >& matrix){ int rows = matrix.size(); if (rows == 0) return matrix; int cols = matrix[0].size(); vector<vector<int> > dist(rows, vector<int>(cols, INT_MAX - 100000)); //First pass: check for left and top for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { if (matrix[i][j] == 0) dist[i][j] = 0; else { if (i > 0) dist[i][j] = min(dist[i][j], dist[i - 1][j] + 1); if (j > 0) dist[i][j] = min(dist[i][j], dist[i][j - 1] + 1); } } } //Second pass: check for bottom and right for (int i = rows - 1; i >= 0; i--) { for (int j = cols - 1; j >= 0; j--) { if (i < rows - 1) dist[i][j] = min(dist[i][j], dist[i + 1][j] + 1); if (j < cols - 1) dist[i][j] = min(dist[i][j], dist[i][j + 1] + 1); } } return dist;}
Complexity analysis
- Time complexity: O(r⋅c). 2 passes of r⋅c each
- Space complexity: O(r⋅c). No additional space required than
dist vector<vector<int> >
public class Solution { public int[][] updateMatrix(int[][] matrix) { if(matrix.length==0) return matrix; for(int i = 0; i<matrix.length; i++) for(int j = 0; j<matrix[0].length; j++) if(matrix[i][j]==1&&!hasNeiberZero(i, j,matrix)) matrix[i][j] = matrix.length+matrix[0].length+1; for(int i = 0; i<matrix.length; i++) for(int j = 0; j<matrix[0].length; j++) if(matrix[i][j]==1) dfs(matrix, i, j, -1); return matrix; } private void dfs(int[][] matrix, int x, int y, int val){ if(x<0||y<0||y>=matrix[0].length||x>=matrix.length||matrix[x][y]<=val) return; if(val>0) matrix[x][y] = val; dfs(matrix, x+1, y, matrix[x][y]+1); dfs(matrix, x-1, y, matrix[x][y]+1); dfs(matrix, x, y+1, matrix[x][y]+1); dfs(matrix, x, y-1, matrix[x][y]+1); } private boolean hasNeiberZero(int x, int y, int[][] matrix){ if(x>0&&matrix[x-1][y]==0) return true; if(x<matrix.length-1&&matrix[x+1][y]==0) return true; if(y>0&&matrix[x][y-1]==0) return true; if(y<matrix[0].length-1&&matrix[x][y+1]==0) return true; return false; }}
public class Solution { int currMin = 12000; // The number of elements of the given matrix will not exceed 10,000, so we can use 12,000 (or anything >10,000) throughout the program as MAX value public int[][] updateMatrix(int[][] matrix) { if (matrix.length == 0 || matrix[0].length == 0) { return matrix; } for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix[i].length; j++) { if (matrix[i][j] == 1) { currMin = 12000; int minDist = dfs(matrix, i, j, 0); if (minDist < 12000) matrix[i][j] = minDist; } } } return matrix; } private int dfs(int[][] matrix, int i, int j, int steps) { if (i < 0 || i >= matrix.length || j < 0 || j >= matrix[0].length ) { return 12000; } if (matrix[i][j] != 1 || steps > currMin) { return matrix[i][j]; } matrix[i][j] ^= 12000; int down = dfs(matrix, i+1, j, steps + 1); int up = dfs(matrix, i-1, j, steps + 1); int left = dfs(matrix, i, j-1, steps + 1); int right = dfs(matrix, i, j+1, steps + 1); matrix[i][j] ^= 12000; int minVal = Math.min(left, Math.min(right, Math.min(up, down))) + 1; currMin = minVal; return minVal; }}15 days ago reply quote
class Solution {public: vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) { for(int row=0;row<matrix.size();row++){ for(int col=0;col<matrix[0].size();col++){ if(matrix[row][col]==1&&no_adjacent_zero(matrix,row,col)) matrix[row][col]=10000; } } for(int row=0;row<matrix.size();row++){ for(int col=0;col<matrix[0].size();col++){ dfs(matrix,row,col); } } return matrix; } bool no_adjacent_zero(vector<vector<int>>& matrix,int row,int col){ int next[4][2]={{0,1},{1,0},{0,-1},{-1,0}}; for(int k=0;k<4;k++){ int new_row=row+next[k][0],new_col=col+next[k][1]; if(new_row<0||new_row>=matrix.size()||new_col<0||new_col>=matrix[0].size()) continue; if(matrix[new_row][new_col]==0) return false; } return true; } void dfs(vector<vector<int>>& matrix,int row,int col){ int next[4][2]={{0,1},{1,0},{0,-1},{-1,0}}; for(int k=0;k<4;k++){ int new_row=row+next[k][0],new_col=col+next[k][1]; if(new_row<0||new_row>=matrix.size()||new_col<0||new_col>=matrix[0].size()) continue; if(matrix[new_row][new_col]>matrix[row][col]+1){ matrix[new_row][new_col]=matrix[row][col]+1; dfs(matrix,new_row,new_col); } } }};所以这里有一个重点就是周围没有0的点要用一个比较大的值覆盖。上一个DFS的解法是只要有1就赋一个大的值。。
- 542. 01 Matrix(深搜/广搜/DP的题目)
- zoj1091经典的广搜题目
- BFS(广搜训练题目)
- 哈理工OJ 2074 逃生(广搜题目)
- 逃离迷宫-----广搜+dp
- HDU1254(广搜+深搜)
- HDU5569 matrix(dp)
- matrix (dp)
- BFS广搜题目【经典训练题】
- 图的创建,深搜,广搜(基于临接表实现)
- 深搜,广搜,图的遍历,基础(updating)
- nyoj 613 免费馅饼 dp+广搜
- 关于穷举、深搜、广搜的思考。
- hdu 1428 挺好的一个题目 记忆化搜索+广搜实现迪杰斯特拉
- 武士风度的牛(广搜)
- hdu1180诡异的楼梯(广搜)
- poj3126(最爱的广搜)
- hdu1372(最爱的广搜)
- web16天学习文件的上传和下载
- 2018网易校招编程题(3)交错01串
- Hdu 3966 Aragorn's Story 树链剖分+树状数组
- 34. Search for a Range
- WinForm多线程+委托防止界面卡死
- 542. 01 Matrix(深搜/广搜/DP的题目)
- Atitit 知识管理之 经济学概论 attilax 学习心得
- 用grunt搭建自动化的web前端开发环境-完整教程 .jshintrc文件里的内容有问题
- CentOS 7下Hbase1.3.1分布式环境搭建
- String 创建对象的问题
- 华为云Linux系统搭建Tomcat环境过程
- 函数中this的值为什么与包含函数this的值无关
- 线性布局LinearLayout 的注意点
- lua hello world