An image is represented by a binary matrix with 0 as a white pixel and 1 as a black pixel. The black pixels are connected, i.e., there is only one black region. Pixels are connected horizontally and vertically. Given the location (x, y) of one of the black pixels, return the area of the smallest (axis-aligned) rectangle that encloses all black pixels.
题目意思还算是非常好理解的,就是白像素-0 黑像素-1,所有黑像素连成的一片 而且这是唯一的一片。现在给你一个初始点(xy)表明这个地方是黑点,现在让返回 包含所有的黑色像素点的最小的矩形的面积。
so all we need to do, is find the top/bottom/right/left black pixel can reach, get their position and calcualte the rectangle area.
idea:
of course we can scan the whole graph, and find the top most/bottom most/left most/right most. and the time complexity will be O(n^2)
but this will never use the input information of (x, y)
codes are like this:
public class Solution {
public int minArea(char[][] image, int x, int y) {
int top = x, bottom = x;
int left = y, right = y;
for (x = 0; x < image.length; ++x) {
for (y = 0; y < image[0].length; ++y) {
if (image[x][y] == '1') {
top = Math.min(top, x);
bottom = Math.max(bottom, x + 1);
left = Math.min(left, y);
right = Math.max(right, y + 1);
}
}
}
return (right - left) * (bottom - top);
}
}
or for a problem like this, it looks like flood problem, and four way dfs it is
class Solution {
private int top, bottom, left, right;
public int minArea(char[][] image, int x, int y) {
if (image == null || image.length == 0 || image[0].length == 0) {
return 0;
}
top = bottom = x;
left = right = y; //this is super important, we can't defaultly initialize them as 0s because that's wrong
dfs(image, x, y);
return (bottom - top + 1) * (right - left + 1);
}
private void dfs(char[][] image, int x, int y) {
if (x < 0 || x >= image.length || y < 0 || y >= image[0].length) {
return;
}
if (image[x][y] == '0') { //remember this, this is super important too
return;
}
top = Math.min(top, x);
bottom = Math.max(bottom, x);
left = Math.min(left, y);
right = Math.max(right, y);
image[x][y] = '0'; //over write the 1s
dfs(image, x - 1, y);
dfs(image, x + 1, y);
dfs(image, x, y - 1);
dfs(image, x, y + 1);
}
}
but how are we gonna solve this using binary search?
this is way too hard for me.
https://leetcode.com/problems/smallest-rectangle-enclosing-black-pixels/solution/
public class Solution {
public int minArea(char[][] image, int x, int y) {
int m = image.length, n = image[0].length;
int left = searchColumns(image, 0, y, 0, m, true);
int right = searchColumns(image, y + 1, n, 0, m, false);
int top = searchRows(image, 0, x, left, right, true);
int bottom = searchRows(image, x + 1, m, left, right, false);
return (right - left) * (bottom - top);
}
private int searchColumns(char[][] image, int i, int j, int top, int bottom, boolean whiteToBlack) {
while (i != j) {
int k = top, mid = (i + j) / 2;
while (k < bottom && image[k][mid] == '0') ++k;
if (k < bottom == whiteToBlack) // k < bottom means the column mid has black pixel
j = mid; //search the boundary in the smaller half
else
i = mid + 1; //search the boundary in the greater half
}
return i;
}
private int searchRows(char[][] image, int i, int j, int left, int right, boolean whiteToBlack) {
while (i != j) {
int k = left, mid = (i + j) / 2;
while (k < right && image[mid][k] == '0') ++k;
if (k < right == whiteToBlack) // k < right means the row mid has black pixel
j = mid;
else
i = mid + 1;
}
return i;
}
}