Given a list of non-overlapping axis-aligned rectangles rects, write a function pick which randomly and uniformily picks an integer point in the space covered by the rectangles.

Note:

  1. An integer point is a point that has integer coordinates.
  2. A point on the perimeter of a rectangle is included in the space covered by the rectangles.
  3. ith rectangle = rects[i] = [x1,y1,x2,y2], where [x1, y1] are the integer coordinates of the bottom-left corner, and [x2, y2] are the integer coordinates of the top-right corner.
  4. length and width of each rectangle does not exceed 2000.
  5. 1 <= rects.length <= 100
  6. pick return a point as an array of integer coordinates [p_x, p_y]
  7. pick is called at most 10000 times.

Example 1:

Input:
["Solution","pick","pick","pick"]
[[[[1,1,5,5]]],[],[],[]]
Output:
[null,[4,1],[4,1],[3,3]]

Example 2:

Input:
["Solution","pick","pick","pick","pick","pick"]
[[[[-2,-2,-1,-1],[1,0,3,0]]],[],[],[],[],[]]
Output:
[null,[-1,-2],[2,0],[-2,-1],[3,0],[-2,-2]]

Explanation of Input Syntax:

The input is two lists: the subroutines called and their arguments. Solution's constructor has one argument, the array of rectangles rectspick has no arguments. Arguments are always wrapped with a list, even if there aren't any.

这道题给了我们一些非重叠的矩形,让我们返回一个这些矩形中的一个随机的点。那么博主的第一直觉就是首先要在这些矩形中随机挑出来一个,然后在这个随机的矩形中再随机生成一个点,通过随机生成一个长和宽即可。博主最开始想到的方法是用rand随机生成一个 [0, n) 范围内的数字,n为输入矩形的个数,这样就得到了一个随机的矩形。但是这种方法貌似行不通,会跪在一个很长的输入测试数据。这使得博主比较困惑了,没有想出原因是为何,有哪位看官大神们知道的,麻烦留言告知博主哈!哈,已经知道了,参见评论区二楼留言~ 论坛上的解法有一种是用水塘抽样Reservoir Sampling的方法的,LeetCode之前有过几道需要用这种方法的题目 Random Pick IndexShuffle an Array 和 Linked List Random Node。这里我们使用其来随机出一个矩形,做法是遍历所有的矩形,用变量sumArea来计算当前遍历过的所有矩形面积之和,然后变量area是当前遍历的矩形的面积(注意这里不是严格意义上的面积,而是该区域内整数坐标的点的个数,所以长宽相乘的时候都要加1),然后我们在当前所有矩形面积之和内随机生成一个值,如果这个值小于area,那么选择当前的矩阵为随机矩形。这里相当于一个大小为area的水塘,在这个值之内的话,就更换selected。这个方法是没啥问题,但是博主还是没想通为啥不能直接随机生成矩形的index。当我们拿到随机矩形后,之后就随机出宽和高返回即可,参见代码如下:

解法一:

class Solution {
public:
Solution(vector<vector<int>> rects) {
_rects = rects;
} vector<int> pick() {
int sumArea = ;
vector<int> selected;
for (auto rect : _rects) {
int area = (rect[] - rect[] + ) * (rect[] - rect[] + );
sumArea += area;
if (rand() % sumArea < area) selected = rect;
}
int x = rand() % (selected[] - selected[] + ) + selected[];
int y = rand() % (selected[] - selected[] + ) + selected[];
return {x, y};
} private:
vector<vector<int>> _rects;
};

这道题在论坛上的主流解法其实是这个,我们用TreeMap来建立当前遍历过的矩形面积之和跟该矩形位置之间的映射。然后当我们求出所有的矩形面积之和后,我们随机生成一个值,然后在TreeMap中找到第一个大于这个值的矩形,这里博主还是有疑问,为啥不能直接随机矩形的位置,而是非要跟面积扯上关系。之后的步骤就跟上面的没啥区别了,参见代码如下:

解法二:

class Solution {
public:
Solution(vector<vector<int>> rects) {
_rects = rects;
_totalArea = ;
for (auto rect : rects) {
_totalArea += (rect[] - rect[] + ) * (rect[] - rect[] + );
_areaToIdx.insert({_totalArea, _areaToIdx.size()});
}
} vector<int> pick() {
int val = rand() % _totalArea;
int idx = _areaToIdx.upper_bound(val)->second;
int width = _rects[idx][] - _rects[idx][] + ;
int height = _rects[idx][] - _rects[idx][] + ;
return {rand() % width + _rects[idx][], rand() % height + _rects[idx][]};
} private:
vector<vector<int>> _rects;
int _totalArea;
map<int, int> _areaToIdx;
};

类似题目:

Random Pick with Weight

Generate Random Point in a Circle

参考资料:

https://leetcode.com/problems/random-point-in-non-overlapping-rectangles/

https://leetcode.com/problems/random-point-in-non-overlapping-rectangles/discuss/155005/C%2B%2B-single-rand()-call

https://leetcode.com/problems/random-point-in-non-overlapping-rectangles/discuss/169185/Short-C%2B%2B-solution-with-upper_bound

https://leetcode.com/problems/random-point-in-non-overlapping-rectangles/discuss/170503/C%2B%2B-solution-using-reservoir-sampling-with-explanation-concise-and-easy-to-understand

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Random Point in Non-overlapping Rectangles 非重叠矩形中的随机点的更多相关文章

  1. [Swift]LeetCode497. 非重叠矩形中的随机点 | Random Point in Non-overlapping Rectangles

    Given a list of non-overlapping axis-aligned rectangles rects, write a function pick which randomly ...

  2. 2017ICPC南宁赛区网络赛 Overlapping Rectangles(重叠矩阵面积和=离散化模板)

    There are nnn rectangles on the plane. The problem is to find the area of the union of these rectang ...

  3. [Swift]LeetCode1031. 两个非重叠子数组的最大和 | Maximum Sum of Two Non-Overlapping Subarrays

    Given an array A of non-negative integers, return the maximum sum of elements in two non-overlapping ...

  4. 在ASP.NET非MVC环境中(WebForm中)构造MVC的URL参数

    目前项目中有个需求,需要在WebForm中去构造MVC的URL信息,这里写了一个帮助类可以在ASP.NET非MVC环境中(WebForm中)构造MVC的URL信息,主要就是借助当前Http上下文去构造 ...

  5. Android 高级UI设计笔记17:Android在非UI线程中显示Toast

    1. 子线程的Toast怎么显示不出来? 因为Toast在创建的时候会依赖于一个Handler,并且一个Handler是需要有一个Looper才能够创建,而普通的线程是不会自动去创建一个Looper对 ...

  6. leetcode 题解:Binary Tree Inorder Traversal (二叉树的中序遍历)

    题目: Given a binary tree, return the inorder traversal of its nodes' values. For example:Given binary ...

  7. 在非MFC程序中引用CString

    CString在当今软件设计界里还是小有名气的,说它是MFC中使用的最多的类一点也不过,然而在使用sdk编windows程序的时候,确不能利用CString类,只能用sdk的运行时库,比如strlen ...

  8. 如何在非 React 项目中使用 Redux

    本文作者:胡子大哈 原文链接:https://scriptoj.com/topic/178/如何在非-react-项目中使用-redux 转载请注明出处,保留原文链接和作者信息. 目录 1.前言 2. ...

  9. 关于C#中”扩展方法必须在非泛型静态类中定义“问题的解决

    问题描述: 在某个窗口下的编码中使用了以下扩展方法FindControl,以求根据字符串的值去操作控件(本文中的控件为Label控件)的属性. public static Control FindCo ...

随机推荐

  1. 用 python 写一个年会抽奖小程序

    使用 pyinstaller 打包工具常用参数指南 pyinstaller -F demo.py 参数 含义 -F 指定打包后只生成一个exe格式的文件 -D –onedir 创建一个目录,包含exe ...

  2. SQLALlchemy数据查询小集合

    SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作.将对象转换成SQL,然后使用数据API执行SQL并获取执行结果.在写项目的过 ...

  3. java集合分割

    java集合分割成等份的小集合: private <T> List<List<T>> getSubList(List list,int len) { if(list ...

  4. 16、爬取知乎大v张佳玮的文章“标题”、“摘要”、“链接”,并存储到本地文件

    爬取知乎大v张佳玮的文章“标题”.“摘要”.“链接”,并存储到本地文件 # 爬取知乎大v张佳玮的文章“标题”.“摘要”.“链接”,并存储到本地文件 # URL https://www.zhihu.co ...

  5. 使用Maven插件构建Spring Boot应用程序镜像

    使用Maven插件构建Spring Boot应用程序的Docker镜像. 环境准备 1.Linux系统 2.安装JDK,Maven 3.安装Docker 应用实践 1.在应用程序根目录下添加Docke ...

  6. 使用SO_REVTIMEO套接字选项为recvfrom设置超时

    void dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen) { int n; ]; struct timeval ...

  7. CodeBlocks(17.12) 代码调试基础方法&快捷方式

    转载:CodeBlocks(17.12) 代码调试基础方法&快捷方式: https://www.cnblogs.com/DCD112358/p/8998053.html

  8. mac 电脑进入root用户

    一.使用命令:sudo su -:命令执行后输入密码

  9. Python 概念小屋

     Python 中的 if __name__ == '__main__' 该如何理解 python多进程的理解 multiprocessing Process join run      

  10. 华为交换机配置stelnet登陆的实例

    作者:邓聪聪 为满足等堡安全要求,对测评对象的交换机做安全登陆的限制 :开启ssh的服务 stelnet server enable :#创建认证用户的用户名和密码 aaa local-user te ...