750. Number Of Corner Rectangles
Given a grid where each entry is only 0 or 1, find the number of corner rectangles.
A corner rectangle is 4 distinct 1s on the grid that form an axis-aligned rectangle. Note that only the corners need to have the value 1. Also, all four 1s used must be distinct.
Example 1:
Input: grid =
[[1, 0, 0, 1, 0],
[0, 0, 1, 0, 1],
[0, 0, 0, 1, 0],
[1, 0, 1, 0, 1]]
Output: 1
Explanation: There is only one corner rectangle, with corners grid[1][2], grid[1][4], grid[3][2], grid[3][4].
Example 2:
Input: grid =
[[1, 1, 1],
[1, 1, 1],
[1, 1, 1]]
Output: 9
Explanation: There are four 2x2 rectangles, four 2x3 and 3x2 rectangles, and one 3x3 rectangle.
Example 3:
Input: grid =
[[1, 1, 1, 1]]
Output: 0
Explanation: Rectangles must have four distinct corners.
Note:
- The number of rows and columns of grid will each be in the range [1, 200].
- Each grid[i][j] will be either 0 or 1.
- The number of 1s in the grid will be at most 6000.
方法0: brute force, TLE
思路:
对每一对column pair(O(n^2)),遍历O(M ^2)列,对第四个点用O(1)的时间查找。
class Solution {
public:
int countCornerRectangles(vector<vector<int>>& grid) {
int m = grid.size(), n = grid[0].size(), res = 0;
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j ++) {
for (int k = 0; k < m - 1; k ++) {
for (int l = k + 1; l < m; l++) {
if (grid[k][i] && grid[l][i] && grid[k][j] && grid[l][j]) res++;
}
}
}
}
return res;
}
};
方法0.1: better brute force
思路:
更改一下循环顺序,先确定左上点,如果不是1直接continue。再确定右上点,不是1退出,最后一个循环内检查下边两个点。
class Solution {
public:
int countCornerRectangles(vector<vector<int>>& grid) {
int m = grid.size(), n = grid[0].size(), res = 0;
for (int i = 0; i < n - 1; i++) {
for (int k = 0; k < m - 1; k ++) {
if (!grid[k][i]) continue;
for (int j = i + 1; j < n; j ++) {
if (!grid[k][j]) continue;
for (int l = k + 1; l < m; l++) {
if (grid[l][i] && grid[l][j]) res++;
}
}
}
}
return res;
}
};
方法1:
思路:
观察发现,为了形成rectangle,必须满足一对column pair在某两行同时有1,但是没有必要对这样的行一次一次的重新扫。当我们知道这一行可以成为一条边之后,只要知道有多少边可以和它pair up就好了。也就是说,我们要知道所有这样边的数量。那么这两列能组成的rectangles就是count * (count - 1) / 2。
Complexity
Time complexity: O(n^2* m)
Space complexity: O(1)
class Solution {
public:
int countCornerRectangles(vector<vector<int>>& grid) {
int m = grid.size(), n = grid[0].size(), res = 0;
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j ++) {
int count = 0;
for (int k = 0; k < m; k ++) {
if (grid[k][i] && grid[k][j]) count++;
}
res += count * (count - 1) / 2;
}
}
return res;
}
};
方法2:
思路:
Again,在复杂度相同的情况下,改变循环顺序,确定能提前确定的点,如果是0直接quit。
Complexity
Time complexity: O(n^2* m)
Space complexity: O(n)
class Solution {
public:
int countCornerRectangles(vector<vector<int>>& grid) {
int m = grid.size(), n = grid[0].size(), res = 0;
for (int i = 0; i < m - 1; i++) {
vector<int> ones;
for (int k = 0; k < n; k++) if (grid[i][k]) ones.push_back(k);
for (int j = i + 1; j < m; j++) {
int count = 0;
for (int l = 0; l < ones.size(); l++) {
if (grid[j][ones[l]]) count++;
}
res += count * (count - 1) / 2;
}
}
return res;
}
};