非重叠矩形中的随机点

简介: 🎈每天进行一道算法题目练习,今天的题目是“非重叠矩形中的随机点”。

说在前面

🎈每天进行一道算法题目练习,今天的题目是“非重叠矩形中的随机点”。

问题描述

给定一个由非重叠的轴对齐矩形的数组 rects ,其中 rects[i] = [ai, bi, xi, yi] 表示 (ai, bi) 是第 i 个矩形的左下角点,(xi, yi) 是第 i 个矩形的右上角角点。设计一个算法来随机挑选一个被某一矩形覆盖的整数点。矩形周长上的点也算做是被矩形覆盖。所有满足要求的点必须等概率被返回。

在一个给定的矩形覆盖的空间内任何整数点都有可能被返回。

请注意 ,整数点是具有整数坐标的点。

实现 Solution 类:

Solution(int[][] rects) 用给定的矩形数组 rects 初始化对象。
int[] pick() 返回一个随机的整数点 [u, v] 在给定的矩形所覆盖的空间内。
 

示例 1:

image.png

输入:

["Solution","pick","pick","pick","pick","pick"]
[[[[-2,-2,1,1],[2,2,4,6]]],[],[],[],[],[]]

输出:

[null,[-1,-2],[2,0],[-2,-1],[3,0],[-2,-2]

解释:

Solution solution = new Solution([[-2, -2, 1, 1], [2, 2, 4, 6]]);
solution.pick(); // 返回 [1, -2]
solution.pick(); // 返回 [1, -1]
solution.pick(); // 返回 [-1, -2]
solution.pick(); // 返回 [-2, -2]
solution.pick(); // 返回 [0, 0]

提示:

1 <= rects.length <= 100
rects[i].length == 4
-10^9 <= ai < xi <= 10^9
-10^9 <= bi < yi <= 10^9
xi - ai <= 2000
yi - bi <= 2000
所有的矩形不重叠。
pick 最多被调用 10^4 次。

思路分析

首先我们应该要先理解题目的题意,题目会给我们一个矩形数组,我们需要从矩形数组覆盖的点集合中随机获取一个点,所有满足要求的点必须等概率被返回。\
理解了题目要求后我们也就可以开始思考应该要怎么做了,最简单直接的做法当然是将所有矩形覆盖的点都统计出来,再随机从所有的点中抽取一个就可以了,但是让我们来看看数据量,数据的大小为:

-10^9 <= ai < xi <= 10^9
-10^9 <= bi < yi <= 10^9

这样直接将所有的点统计出来必然会超出时间限制,所以这个做法不行,我们应该要换个思路再想想。我们可以先确定一个矩形,然后在从矩形中随机找一个点吗?当然可以,只要注意下面这一点就可以了:
所有满足要求的点必须等概率被返回。所有的点被返回的概率相等,即矩形中的点数也多(矩形越大),该矩形被选中的概率越大。所以我们应该要先确认矩形被选中的概率,而后等概率抽取出一个矩形,在从矩形中抽取一个点,这样计算出的答案就是满足题意的,所有的点被返回的概率相等

  • 1、计算每个矩形被选中的概率

计算所有矩形覆盖面积的点数num,再统计每个矩形覆盖的点数map[i],则每个矩形被选中的概率为map[i] / num;

rects.map(item=>{
    num += (item[2] - item[0] + 1) * (item[3] - item[1] + 1);
    map.push(num);
});
  • 2、随机选择一个矩形

前面我们确定了所有矩形覆盖面积的点数,以及每个矩形的覆盖点数,所以我们可以从所有点数中随机抽取一个,然后在判断它位于哪个矩形中即可。

const num = this.getRandomNum(1,this.num);
let ind = 0;
while(!((this.map[ind - 1] || 0) <= num && num <= this.map[ind])) ind++;
const rect = this.rects[ind];
  • 3、从矩形中随机选择一个点

确认了选中的矩形之后,我们就可以直接从矩形中随机获取一个点了。

const x = this.getRandomNum(rect[0],rect[2]);
const y = this.getRandomNum(rect[1],rect[3]);
return [x,y];

AC代码

/**
 * @param {number[][]} rects
 */
 var Solution = function(rects) {
    this.rects = rects;
    let num = 0;
    let map = [];
    rects.map(item=>{
        num += (item[2] - item[0] + 1) * (item[3] - item[1] + 1);
        map.push(num);
    });
    this.map = map;
    this.num = num;
};
Solution.prototype.getRandomNum = function(minNum, maxNum) {
    minNum = parseInt(minNum);
    maxNum = parseInt(maxNum);
    const res = Math.floor(Math.random() * (maxNum - minNum + 1)) + minNum;
    return res;
};
Solution.prototype.pick = function() {
    const num = this.getRandomNum(1,this.num);
    let ind = 0;
    while(!((this.map[ind - 1] || 0) <= num && num <= this.map[ind])) ind++;
    const rect = this.rects[ind];
    const x = this.getRandomNum(rect[0],rect[2]);
    const y = this.getRandomNum(rect[1],rect[3]);
    return [x,y];
};

/**
 * Your Solution object will be instantiated and called as such:
 * var obj = new Solution(rects)
 * var param_1 = obj.pick()
 */

说在后面

🎉这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打打羽毛球🏸 ,平时也喜欢写些东西,既为自己记录📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解🙇,写错的地方望指出,定会认真改进😊,在此谢谢大家的支持,我们下文再见🙌。
目录
相关文章
|
算法 前端开发
圆和矩形是否有重叠
圆和矩形是否有重叠
100 0
|
算法 测试技术 C#
C++前缀和算法应用:矩形区域不超过 K 的最大数值和
C++前缀和算法应用:矩形区域不超过 K 的最大数值和
|
4月前
|
算法 C++ Windows
空间射线与三角形相交算法的两种实现
空间射线与三角形相交算法的两种实现
50 0
|
4月前
|
算法
空间点与直线距离算法
空间点与直线距离算法
61 0
|
7月前
|
存储 算法 Java
给定一组棋子的坐标,判断是否可以互相攻击。如果两个棋子的横纵坐标任意一个相同,则认为它们可以互相攻击。(提示:使用哈希表)
给定一组棋子的坐标,判断是否可以互相攻击。如果两个棋子的横纵坐标任意一个相同,则认为它们可以互相攻击。(提示:使用哈希表)
55 0
|
7月前
leetcode-1725:可以形成最大正方形的矩形数目
leetcode-1725:可以形成最大正方形的矩形数目
42 0
|
人工智能 算法 BI
利用矩阵进行平移,旋转,缩放等图像变换、创建第二个一模一样的图像并使之进行缩放等操作
利用矩阵进行平移,旋转,缩放等图像变换、创建第二个一模一样的图像并使之进行缩放等操作
|
Rust 自然语言处理 算法
【算法】1725. 可以形成最大正方形的矩形数目(多语言实现)
给你一个数组 rectangles ,其中 rectangles[i] = [li, wi] 表示第 i 个矩形的长度为 li 、宽度为 wi 。 如果存在 k 同时满足 k <= li 和 k <= wi ,就可以将第 i 个矩形切成边长为 k 的正方形。例如,矩形 [4,6] 可以切成边长最大为 4 的正方形。 设 maxLen 为可以从矩形数组 rectangles 切分得到的 最大正方形 的边长。 请你统计有多少个矩形能够切出边长为 maxLen 的正方形,并返回矩形 数目 。
|
存储 索引
区间重叠问题(排序or边界)
区间重叠问题(排序or边界)

热门文章

最新文章