Problem
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
Solution
最主要是知道一个定理 refer :
here
If there are only one black pixel region, then in a projected 1D array all the black pixels are connected.
这样就用正常的 binary search 就好了
class Solution {
int getHorizan(const vector<vector<char>>& image, int left, int right, bool flag){
while(left <= right){
int mid = (left + right)/2 , k = 0;
while( k < image.size() && image[k][mid] == '0') k++;
if( k != image.size()){
flag ? right = mid - 1 : left = mid + 1;
}
else {
flag ? left = mid + 1 : right = mid - 1;
}
}
return flag ? left : right;
}
int getVertical(const vector<vector<char>>& image, int top, int bottom, bool flag){
while( top <= bottom){
int mid = ( top + bottom) / 2 , k = 0;
while(k < image[0].size() && image[mid][k] == '0' ){
k++;
}
if( k != image[0].size() ){
flag ? bottom = mid -1 : top = mid + 1;
}
else {
flag ? top = mid + 1 : bottom = mid - 1;
}
}
return flag ? top : bottom;
}
public:
int minArea(vector<vector<char>>& image, int x, int y) {
if(image.empty() || image[0].empty()) return 0;
int M = image.size(), N = image[0].size();
int leftBoard = getHorizan(image, 0, y, true);
int rightBoard = getHorizan(image, y, N - 1, false);
int topBoard = getVertical(image, 0, x, true);
int bottomBoard = getVertical(image, x, M -1, false);
return (rightBoard - leftBoard + 1) *( bottomBoard - topBoard + 1);
}
};
Solution 2
还有一个比较straigtforward的方法,就是 bfs
时间复杂度明显不如binary search
需要注意几点
1. unordered_set 中的key不能是pair
2. 计算 visited 的idx时 , x*N, 而不是 x*M
class Solution {
public:
int minArea(vector<vector<char>>& image, int x, int y) {
const int M = image.size(), N = image[0].size();
queue<pair<int,int>> toVisit;
vector<bool> visited ( M*N, false);
vector<pair<int,int>> lib = {
make_pair(0,1), make_pair(0,-1), make_pair(-1,0), make_pair(1,0)
};
int leftMost = y, rightMost = y , upMost = x, downMost = x;
toVisit.push(make_pair(x,y));
int idx = x*N + y;
visited[idx] = true;
while(!toVisit.empty()){
pair<int,int> curPair = toVisit.front();
int curX = curPair.first, curY = curPair.second;
toVisit.pop();
leftMost = min(leftMost, curY);
rightMost = max(rightMost, curY);
upMost = min(upMost, curX);
downMost = max(downMost, curX);
for( auto p : lib){
int nextX = curX + p.first, nextY = curY + p.second;
if(nextX == -1 ||nextX == M || nextY == N || nextY == -1) continue;
int idx = nextX*N + nextY;
if(!visited[idx] && image[nextX][nextY] == '1') {
toVisit.push(make_pair(nextX, nextY));
visited[idx] = true;
}
}
}
return (rightMost - leftMost + 1) * (downMost - upMost + 1);
}
};