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]]
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.
数学题。
1.Map<Integer, Map<Integer, Integer>>。O(~边长^3)。
遍历每一行,考虑在前面定好的情况下插入当前行会怎么增加长方形数。在这一行里二重循环遍历所有列的组合[l,r],对lr的位置都是1的有效组合,如果之前记录过前面所有行[l,r]也为1的次数cnt,那么直接把cnt拿过来就是此时新增的正方形数了。同时记得根据这行更新维护cnt的MAP<MAP>。
2.组合计算。O(~边长^3)。
两行两行的组合[u, d]一起遍历。二重循环内部再用一个列指针j扫过去,看这两行里,同一列正好都是1的点对有几个,存到计数器n里。那么这两行所有的正方形数,也就是这n个双点对任选其二的组合: Cn2 = n*(n-1)/2了。遍历完所有行行的组合就有答案了。
实现1:
class Solution { public int countCornerRectangles(int[][] grid) { Map<Integer, Map<Integer, Integer>> map = new HashMap<>(); int ans = 0; for (int i = 0; i < grid.length; i++) { for (int l = 0; l < grid[0].length; l++) { if (grid[i][l] == 0) { continue; } for (int r = l + 1; r < grid[0].length; r++) { if (grid[i][r] == 0) { continue; } if (map.containsKey(l) && map.get(l).containsKey(r)) { ans += map.get(l).get(r); } map.putIfAbsent(l, new HashMap<Integer, Integer>()); map.get(l).put(r, map.get(l).getOrDefault(r, 0) + 1); } } } return ans; } }
实现2:
class Solution { public int countCornerRectangles(int[][] grid) { if (grid == null || grid.length == 0 || grid[0].length == 0) { return 0; } int ans = 0; for (int u = 0; u < grid.length; u++) { for (int d = u + 1; d < grid.length; d++) { int cnt = 0; for (int j = 0; j < grid[0].length; j++) { if (grid[u][j] == 1 && grid[d][j] == 1) { cnt++; } } ans += cnt * (cnt - 1) / 2; } } return ans; } }
小优化:
class Solution { public int countCornerRectangles(int[][] grid) { List<List<Integer>> dense = new ArrayList<>(); Map<Integer, Map<Integer, Integer>> map = new HashMap<>(); for (int i = 0; i < grid.length; i++) { dense.add(new ArrayList<Integer>()); for (int j = 0; j < grid[0].length; j++) { if (grid[i][j] == 1) { dense.get(i).add(j); } } } int ans = 0; for (int i = 0; i < grid.length; i++) { for (int cnt1 = 0; cnt1 < dense.get(i).size(); cnt1++) { int l = dense.get(i).get(cnt1); for (int cnt2 = cnt1 + 1; cnt2 < dense.get(i).size(); cnt2++) { int r = dense.get(i).get(cnt2); if (map.containsKey(l) && map.get(l).containsKey(r)) { ans += map.get(l).get(r); } map.putIfAbsent(l, new HashMap<Integer, Integer>()); map.get(l).put(r, map.get(l).getOrDefault(r, 0) + 1); } } } return ans; } }