列表

详情


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] 。

 

提示:

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class Solution { public: vector<int> countRectangles(vector<vector<int>>& rectangles, vector<vector<int>>& 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]

上一题