Description
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 0
0 1 0
0 0 0
Output:
0 0 0
0 1 0
0 0 0
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.
Analyze
Firstly, we will notice that the given function name is updateMatrix while not findClosest or something, which means I don’t need new space to solve the problem, just updating instead.
I didn’t use DFS although I search the problem by this tag, but I found many good particularities in this problem:
- Traverse and update the matrix, and we can ignore 0.
- We already knew the updated above value and left value because of the sequence of traverse.
- If there exist less steps than above or left value + 1, than the corresponding nearer zero must be in lower right corner.
That’s all of the main points.
Detail
How to find the nearest zero in the lower right corner?
I use a variable called step, the elements we can reach from matrix[i][j] in step are matrix[i + k][j + step - k](k from 0 to step). So we can have them in a loop.
Another trouble is how to deal with ArrayIndexOutOfBounds.
code
vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) {
int row = matrix.size();
int col = matrix[0].size();
for(int i = 0; i < row; ++i) {
for(int j = 0; j < col; ++j) {
if(matrix[i][j] != 0) {
int above = (i - 1 >= 0) ? (matrix[i - 1][j] + 1) : 10000;
int left = (j - 1 >= 0) ? (matrix[i][j - 1] + 1) : 10000;
int less = above > left ? left : above;
int step = 0;
int step_max = row - 1 - i + col - 1 - j;
if(less < step_max) step_max = less - 1;
bool found = false;
while(step < step_max && !found) {
++step;
for(int k = 0; k <= step; k++) {
if(i + k >= row || j + step - k >= col) continue;
if(matrix[i + k][j + step - k] == 0) {
found = true;
break;
}
}
}
matrix[i][j] = (found && less > step) ? step : less;
}
}
}
return matrix;
}
TLE
The last input is [[0, 1], [0, 1], [0, 1]……[0, 1]] when I got TLE. This is because I spent a lot of time in searching those out-of-bound matrix[i + k][j + step - k]. Then I found two ways to improve my algorithm.
One of them is setting a step_max as I did in code. Step_max is min{above, left}, so we can avoid serarching too far if the solution in lower right coner is worse. And I got AC after I made this improvement.
Another one is a trick. It’s not hard to see that, once we have a “shortest path”, then the value of sub-matrix, whose top left corner is the source of the shortest path, and the lower right corner is the destination of the shortest path, can be settled. But since I have got AC, I did’t perform that.
//this could be done in one round
1 1 1 1 6 5 4 3
1 1 1 1 5 4 3 2
1 1 1 1 --> 4 3 2 1
1 1 1 0 3 2 1 0
Summary
BFS is an obvious solution at very first. However, I blame my poor Data Struct learning that I do not like graph algorithm. So I didn’t choose BFS and found a more interesting solution.
As graph algorithm is my weakness, I also checked others’ code and I will practice it in the next puzzle.