题目:
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.
For example, given the following image:
[ "0010", "0110", "0100" ]and
x
= 0, y
= 2,
Return 6.
思路:
1、DFS:首先想到的就是深度优先搜索。从位置 (x, y) 开始深度搜索它的四个邻居,在搜索的过程中维护四个边界,最后返回四个边界所对应的面积即可。该算法的时间复杂度是O(m*n),其中m和n分别是图像的高度和宽度。DFS应该是一个可以通过面试的算法了,当然这道题目用BFS我觉得也是可以解决的。
2、二分查找:还有一个更加巧妙、时间复杂度更低的算法。1)采用二分法在[0, y]区间内搜索每一行,找出最先出现‘1’的那一列,这样就确定了左边界left;2)采用二分法在[y + 1, col_num)区间内搜索每一行,找出最后出现‘0’的那一列,这样就确定了右边界right;3)采用二分法在[left, right]区间内找出最先出现‘1’的那一行,这样就确定了上边界up;4)采用二分法在[left, right]区间内找出最后出现‘0’的那一行,这样就确定了下边界down。四个边界都确定之后,就可以计算并返回包围盒的面积了。假设图像的高度和宽度分别是m和n,则算法的时间复杂度是O(mlogn + nlogm)。在实现中为了减少代码行数,将不同搜索函数整合在一起了,不过总体思路就是这么简单。
代码:
1、DFS:
class Solution {
public:
int minArea(vector<vector<char>>& image, int x, int y) {
if(image.size() == 0 || image[0].size() == 0) {
return 0;
}
left = up = INT_MAX, right = down = INT_MIN;
int row_num = image.size(), col_num = image[0].size();
vector<vector<bool>> visited(row_num, vector<bool>(col_num, false));
for(int r = 0; r < row_num; ++r) {
for(int c = 0; c < col_num; ++c) {
dfs(image, visited, r, c);
}
}
return (right - left + 1) * (down - up + 1);
}
private:
void dfs(vector<vector<char>>& image, vector<vector<bool>>& visited, int row, int col) {
int row_num = image.size(), col_num = image[0].size();
if(row < 0 || row >= row_num || col < 0 || col >= col_num ||
visited[row][col] || image[row][col] == '0') {
return;
}
left = min(left, col), right = max(right, col);
up = min(up, row), down = max(down, row);
visited[row][col] = true;
dfs(image, visited, row - 1, col);
dfs(image, visited, row + 1, col);
dfs(image, visited, row, col - 1);
dfs(image, visited, row, col + 1);
}
int left, right, up, down;
};
2、二分查找:
class Solution {
public:
int minArea(vector<vector<char>>& image, int x, int y) {
if(!image.size() || !image[0].size()) {
return 0;
}
int row_num = image.size(), col_num = image[0].size();
// find the leftmost '1' in the range [0, row_num]
int left = horizontalSearch(0, y, 0, row_num, image, '1');
// find the rightmost '1' in the range [0, row_num] by searching 0
int right = horizontalSearch(y + 1, col_num, 0, row_num, image, '0');
// find the upmost '1' in the range [left, right]
int up = verticalSearch(0, x, left, right, image, '1');
// find the downmost '1' in the range [left, right] by searching 0
int down = verticalSearch(x + 1, row_num, left, right, image, '0');
return (right - left) * (down - up);
}
private:
// the time complexity is O(log(end - start) * (bottom - up))
int horizontalSearch(int start, int end, int top, int bottom, vector<vector<char>>& image, char target) {
while(start < end) {
int mid = start + (end - start) / 2;
int temp_top = top;
char found = '0';
while(temp_top < bottom) {
if (image[temp_top++][mid] == '1') {
found = '1';
break;
}
}
if(target == found) {
end = mid;
}
else {
start = mid + 1;
}
}
return start;
}
// the time complexity is O(log(end - start) * (right - left))
int verticalSearch(int start, int end, int left, int right, vector<vector<char>>& image, char target) {
while(start < end) {
int mid = start + (end - start) / 2;
int temp_left = left;
char found = '0';
while(temp_left < right) {
if(image[mid][temp_left++] == '1') {
found = '1';
break;
}
}
if(target == found) {
end = mid;
}
else {
start = mid + 1;
}
}
return start;
}
};
这篇博客主要介绍了LeetCode中的问题302,如何找到最小的矩形来包围图像中的所有黑色像素。作者提出了两种解决方案:1) 使用深度优先搜索(DFS),从给定的黑色像素位置开始搜索,时间复杂度为O(m*n),m和n是图像的高度和宽度。2) 使用二分查找法,时间复杂度更优,为O(mlogn + nlogm)。文章还给出了DFS和二分查找的代码实现。
308

被折叠的 条评论
为什么被折叠?



