class Solution {
public:
vector<int> countRectangles(vector<vector<int>>& rectangles, vector<vector<int>>& points) {
}
};
2250. 统计包含每个点的矩形数目
给你一个二维整数数组 rectangles
,其中 rectangles[i] = [li, hi]
表示第 i
个矩形长为 li
高为 hi
。给你一个二维整数数组 points
,其中 points[j] = [xj, yj]
是坐标为 (xj, yj)
的一个点。
第 i
个矩形的 左下角 在 (0, 0)
处,右上角 在 (li, hi)
。
请你返回一个整数数组 count
,长度为 points.length
,其中 count[j]
是 包含 第 j
个点的矩形数目。
如果 0 <= xj <= li
且 0 <= yj <= hi
,那么我们说第 i
个矩形包含第 j
个点。如果一个点刚好在矩形的 边上 ,这个点也被视为被矩形包含。
示例 1:
输入:rectangles = [[1,2],[2,3],[2,5]], points = [[2,1],[1,4]] 输出:[2,1] 解释: 第一个矩形不包含任何点。 第二个矩形只包含一个点 (2, 1) 。 第三个矩形包含点 (2, 1) 和 (1, 4) 。 包含点 (2, 1) 的矩形数目为 2 。 包含点 (1, 4) 的矩形数目为 1 。 所以,我们返回 [2, 1] 。
示例 2:
输入:rectangles = [[1,1],[2,2],[3,3]], points = [[1,3],[1,1]] 输出:[1,3] 解释: 第一个矩形只包含点 (1, 1) 。 第二个矩形只包含点 (1, 1) 。 第三个矩形包含点 (1, 3) 和 (1, 1) 。 包含点 (1, 3) 的矩形数目为 1 。 包含点 (1, 1) 的矩形数目为 3 。 所以,我们返回 [1, 3] 。
提示:
1 <= rectangles.length, points.length <= 5 * 104
rectangles[i].length == points[j].length == 2
1 <= li, xj <= 109
1 <= hi, yj <= 100
rectangles
互不相同 。points
互不相同 。原站题解
java 解法, 执行用时: 334 ms, 内存消耗: 70.7 MB, 提交时间: 2023-10-02 00:31:42
class Solution { public int[] countRectangles1(int[][] rectangles, int[][] points) { Arrays.sort(rectangles, (a, b) -> b[1] - a[1]); var n = points.length; var ids = IntStream.range(0, n).boxed().toArray(Integer[]::new); Arrays.sort(ids, (i, j) -> points[j][1] - points[i][1]); var ans = new int[n]; var xs = new ArrayList<Integer>(); var i = 0; for (var id : ids) { var start = i; while (i < rectangles.length && rectangles[i][1] >= points[id][1]) xs.add(rectangles[i++][0]); if (start < i) Collections.sort(xs); // 只有在 xs 插入了新元素时才排序 ans[id] = i - lowerBound(xs, points[id][0]); } return ans; } public int[] countRectangles2(int[][] rectangles, int[][] points) { Arrays.sort(rectangles, (a, b) -> b[0] - a[0]); var n = points.length; var ids = IntStream.range(0, n).boxed().toArray(Integer[]::new); Arrays.sort(ids, (i, j) -> points[j][0] - points[i][0]); var ans = new int[n]; var cnt = new int[101]; var i = 0; for (var id : ids) { while (i < rectangles.length && rectangles[i][0] >= points[id][0]) ++cnt[rectangles[i++][1]]; for (var j = points[id][1]; j < cnt.length; ++j) ans[id] += cnt[j]; } return ans; } public int[] countRectangles(int[][] rectangles, int[][] points) { List<Integer>[] xs = new List[101]; Arrays.setAll(xs, e -> new ArrayList<>()); for (var r : rectangles) xs[r[1]].add(r[0]); for (var x : xs) Collections.sort(x); var n = points.length; var ans = new int[n]; for (var i = 0; i < n; ++i) for (var j = points[i][1]; j <= 100; j++) ans[i] += xs[j].size() - lowerBound(xs[j], points[i][0]); return ans; } int lowerBound(List<Integer> xs, int x) { int left = 0, right = xs.size(); while (left < right) { var mid = (left + right) / 2; if (xs.get(mid) >= x) right = mid; else left = mid + 1; } return left; } }
cpp 解法, 执行用时: 688 ms, 内存消耗: 82.3 MB, 提交时间: 2023-10-02 00:30:15
class Solution { public: // 按纵坐标排序 vector<int> countRectangles1(vector<vector<int>> &rectangles, vector<vector<int>> &points) { sort(rectangles.begin(), rectangles.end(), [](auto &a, auto &b) { return a[1] > b[1]; }); int n = points.size(); vector<int> ids(n); iota(ids.begin(), ids.end(), 0); sort(ids.begin(), ids.end(), [&](int i, int j) { return points[i][1] > points[j][1]; }); vector<int> ans(n), xs; int i = 0; for (int id : ids) { int start = i; while (i < rectangles.size() && rectangles[i][1] >= points[id][1]) xs.push_back(rectangles[i++][0]); if (start < i) sort(xs.begin(), xs.end()); // 只有在 xs 插入了新元素时才排序 ans[id] = xs.end() - lower_bound(xs.begin(), xs.end(), points[id][0]); } return ans; } // 按横坐标排序 vector<int> countRectangles2(vector<vector<int>> &rectangles, vector<vector<int>> &points) { sort(rectangles.begin(), rectangles.end(), [](auto &a, auto &b) { return a[0] > b[0]; }); int n = points.size(); vector<int> ids(n); iota(ids.begin(), ids.end(), 0); sort(ids.begin(), ids.end(), [&](int i, int j) { return points[i][0] > points[j][0]; }); vector<int> ans(n), cnt(101); int i = 0; for (int id : ids) { while (i < rectangles.size() && rectangles[i][0] >= points[id][0]) ++cnt[rectangles[i++][1]]; ans[id] = accumulate(cnt.begin() + points[id][1], cnt.end(), 0); } return ans; } // 按行统计 + 二分查找 vector<int> countRectangles(vector<vector<int>> &rectangles, vector<vector<int>> &points) { vector<int> xs[101]; for (auto &r: rectangles) xs[r[1]].push_back(r[0]); for (auto &x: xs) sort(x.begin(), x.end()); int n = points.size(); vector<int> ans(n); for (int i = 0; i < n; ++i) for (int y = points[i][1]; y <= 100; ++y) { auto &x = xs[y]; ans[i] += x.end() - lower_bound(x.begin(), x.end(), points[i][0]); } return ans; } };
golang 解法, 执行用时: 308 ms, 内存消耗: 14.7 MB, 提交时间: 2023-10-02 00:28:43
func countRectangles1(rectangles [][]int, points [][]int) []int { sort.Slice(rectangles, func(i, j int) bool { return rectangles[i][1] > rectangles[j][1] }) for i := range points { points[i] = append(points[i], i) } sort.Slice(points, func(i, j int) bool { return points[i][1] > points[j][1] }) ans := make([]int, len(points)) i, n, xs := 0, len(rectangles), []int{} for _, p := range points { start := i for ; i < n && rectangles[i][1] >= p[1]; i++ { xs = append(xs, rectangles[i][0]) } if start < i { // 只有在 xs 插入了新元素时才排序 sort.Ints(xs) } ans[p[2]] = i - sort.SearchInts(xs, p[0]) } return ans } func countRectangles2(rectangles [][]int, points [][]int) []int { sort.Slice(rectangles, func(i, j int) bool { return rectangles[i][0] > rectangles[j][0] }) for i := range points { points[i] = append(points[i], i) } sort.Slice(points, func(i, j int) bool { return points[i][0] > points[j][0] }) ans := make([]int, len(points)) i, cnt := 0, [101]int{} for _, p := range points { for ; i < len(rectangles) && rectangles[i][0] >= p[0]; i++ { cnt[rectangles[i][1]]++ } for _, c := range cnt[p[1]:] { ans[p[2]] += c } } return ans } func countRectangles(rectangles [][]int, points [][]int) []int { xs := [101][]int{} for _, r := range rectangles { xs[r[1]] = append(xs[r[1]], r[0]) } for _, x := range xs { sort.Ints(x) } ans := make([]int, len(points)) for i, p := range points { for _, x := range xs[p[1]:] { ans[i] += len(x) - sort.SearchInts(x, p[0]) } } return ans }
python3 解法, 执行用时: 1080 ms, 内存消耗: 34.3 MB, 提交时间: 2023-10-02 00:27:48
class Solution: # 按纵坐标排序 def countRectangles1(self, rectangles: List[List[int]], points: List[List[int]]) -> List[int]: rectangles.sort(key=lambda r: -r[1]) n = len(points) ans = [0] * n i, xs = 0, [] for (x, y), id in sorted(zip(points, range(n)), key=lambda x: -x[0][1]): start = i while i < len(rectangles) and rectangles[i][1] >= y: xs.append(rectangles[i][0]) i += 1 if start < i: xs.sort() # 只有在 xs 插入了新元素时才排序 ans[id] = i - bisect_left(xs, x) return ans # 如果纵坐标范围也是10^9 def countRectangles2(self, rectangles: List[List[int]], points: List[List[int]]) -> List[int]: from sortedcontainers import SortedList rectangles.sort(key=lambda r: -r[1]) n = len(points) ans = [0] * n i, xs = 0, SortedList() for (x, y), id in sorted(zip(points, range(n)), key=lambda x: -x[0][1]): while i < len(rectangles) and rectangles[i][1] >= y: xs.add(rectangles[i][0]) i += 1 ans[id] = i - xs.bisect_left(x) return ans # 按横坐标排序 def countRectangles3(self, rectangles: List[List[int]], points: List[List[int]]) -> List[int]: rectangles.sort(key=lambda r: -r[0]) n = len(points) ans = [0] * n cnt = [0] * (max(y for _, y in rectangles) + 1) i = 0 for (x, y), id in sorted(zip(points, range(n)), key=lambda x: -x[0][0]): while i < len(rectangles) and rectangles[i][0] >= x: cnt[rectangles[i][1]] += 1 i += 1 ans[id] = sum(cnt[y:]) return ans # 按行统计+二分 def countRectangles(self, rectangles: List[List[int]], points: List[List[int]]) -> List[int]: max_y = max(y for _, y in rectangles) xs = [[] for _ in range(max_y + 1)] for x, y in rectangles: xs[y].append(x) for x in xs: x.sort() return [sum(len(x) - bisect_left(x, px) for x in xs[py:]) for px, py in points]