Welcome to Subscribe On Youtube
Question
Formatted question description: https://leetcode.ca/all/302.html
302 Smallest Rectangle Enclosing Black Pixels
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.
Algorithm
Key point:
there is only one black region. 只有一个黑区
So, no need to worry about 1
s spread across the matrix.
Brute force: Traverse the entire array, if it encounters 1, update the rectangle.
Improvement, with a given black pixel (x, y)
as the center, use the binary search to quickly find the upper, lower, left, and right critical points of the entire black area, and then directly calculate the area.
Code
Java
-
public class Smallest_Rectangle_Enclosing_Black_Pixels { public class Solution_BinarySearch { /** * @param image: a binary matrix with '0' and '1' * @param x: the location of one of the black pixels * @param y: the location of one of the black pixels * @return: an integer */ public int minArea(char[][] image, int x, int y) { if (image == null || image.length == 0) { return 0; } int m = image.length; int n = image[0].length; int up = binarySearch(image, true, 0, x, 0, n, true); int down = binarySearch(image, true, x + 1, m, 0, n, false); int left = binarySearch(image, false, 0, y, up, down, true); // @note: re-use up/down to narrow down int right = binarySearch(image, false, y + 1, n, up, down, false); return (right - left) * (down - up); } int binarySearch(char[][] image, boolean isHorizontal, int i, int j, int low, int high, boolean opt) { while (i < j) { int k = low; int mid = (i + j) / 2; while (k < high && (isHorizontal ? image[mid][k] : image[k][mid]) == '0') { ++k; } if (k < high == opt) { j = mid; } else { i = mid + 1; } } return i; } } class Solution_BruteForce { public int minArea(char[][] image, int x, int y) { int rows = image.length, columns = image[0].length; int top = x, bottom = x, left = y, right = y; int[][] directions = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} }; image[x][y] = '2'; Queue<int[]> queue = new LinkedList<int[]>(); queue.offer(new int[]{x, y}); while (!queue.isEmpty()) { int[] cell = queue.poll(); int row = cell[0], column = cell[1]; for (int[] direction : directions) { int newRow = row + direction[0], newColumn = column + direction[1]; if (newRow >= 0 && newRow < rows && newColumn >= 0 && newColumn < columns && image[newRow][newColumn] == '1') { image[newRow][newColumn] = '2'; top = Math.min(top, newRow); bottom = Math.max(bottom, newRow); left = Math.min(left, newColumn); right = Math.max(right, newColumn); queue.offer(new int[]{newRow, newColumn}); } } } return (bottom - top + 1) * (right - left + 1); } } }
-
// OJ: https://leetcode.com/problems/smallest-rectangle-enclosing-black-pixels/ // Time: O(MlogN + NlogM) // Space: O(M + N) class Solution { public: int minArea(vector<vector<char>>& A, int x, int y) { int M = A.size(), N = A[0].size(); auto getRowLength = [&]() { int L = 0, R = x; // search min x while (L <= R) { int mid = (L + R) / 2, j = 0; while (j < N && A[mid][j] == '0') ++j; if (j < N) R = mid - 1; else L = mid + 1; } int mn = L; // minX = L L = x, R = M - 1; while (L <= R) { int mid = (L + R) / 2, j = 0; while (j < N && A[mid][j] == '0') ++j; if (j < N) L = mid + 1; else R = mid - 1; } return L - mn; // maxX = R = L - 1 }; auto getColumnLength = [&]() { int L = 0, R = y; // search min y while (L <= R) { int mid = (L + R) / 2, i = 0; while (i < M && A[i][mid] == '0') ++i; if (i < M) R = mid - 1; else L = mid + 1; } int mn = L; // minY = L L = y, R = N - 1; while (L <= R) { int mid = (L + R) / 2, i = 0; while (i < M && A[i][mid] == '0') ++i; if (i < M) L = mid + 1; else R = mid - 1; } return L - mn; // maxX = R = L - 1 }; return getRowLength() * getColumnLength(); } };
-
class Solution: def minArea(self, image: List[List[str]], x: int, y: int) -> int: m, n = len(image), len(image[0]) left, right = 0, x while left < right: mid = (left + right) >> 1 c = 0 while c < n and image[mid][c] == '0': c += 1 if c < n: right = mid else: left = mid + 1 u = left left, right = x, m - 1 while left < right: mid = (left + right + 1) >> 1 c = 0 while c < n and image[mid][c] == '0': c += 1 if c < n: left = mid else: right = mid - 1 d = left left, right = 0, y while left < right: mid = (left + right) >> 1 r = 0 while r < m and image[r][mid] == '0': r += 1 if r < m: right = mid else: left = mid + 1 l = left left, right = y, n - 1 while left < right: mid = (left + right + 1) >> 1 r = 0 while r < m and image[r][mid] == '0': r += 1 if r < m: left = mid else: right = mid - 1 r = left return (d - u + 1) * (r - l + 1) ############ from collections import deque class Solution(object): def minArea(self, image, x, y): top = self.searchRows(image, 0, x, True) bottom = self.searchRows(image, x + 1, len(image), False) left = self.searchCols(image, 0, y, top, bottom, True) right = self.searchCols(image, y + 1, len(image[0]), top, bottom, False) return (right - left) * (bottom - top) def searchRows(self, image, i, j, opt): while i < j: mid = i + (j - i) / 2 if ("1" in image[mid]) == opt: j = mid else: i = mid + 1 return j def searchCols(self, image, i, j, top, bottom, opt): while i < j: mid = i + (j - i) / 2 # if transpos image, then still can use above one: if ("1" in image[mid]) == opt: if any([image[k][mid] == "1" for k in range(top, bottom)]) == opt: j = mid else: i = mid + 1 return j