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:

  1. The number of rows and columns of grid will each be in the range [1, 200].
  2. Each grid[i][j] will be either 0 or 1.
  3. 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;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值