[LeetCode] Random Point in Non-overlapping Rectangles 非重疊矩形中的隨機點

 

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.html

Note:app

  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:dom

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

Example 2:post

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.spa

 

這道題給了咱們一些非重疊的矩形,讓咱們返回一個這些矩形中的一個隨機的點。那麼博主的第一直覺就是首先要在這些矩形中隨機挑出來一個,而後在這個隨機的矩形中再隨機生成一個點,經過隨機生成一個長和寬便可。博主最開始想到的方法是用rand隨機生成一個 [0, n) 範圍內的數字,n爲輸入矩形的個數,這樣就獲得了一個隨機的矩形。可是這種方法貌似行不通,會跪在一個很長的輸入測試數據。這使得博主比較困惑了,沒有想出緣由是爲什麼,有哪位看官大神們知道的,麻煩留言告知博主哈!哈,已經知道了,參見評論區二樓留言~ 論壇上的解法有一種是用水塘抽樣Reservoir Sampling的方法的,LeetCode以前有過幾道須要用這種方法的題目 Random Pick IndexShuffle an Array 和 Linked List Random Node。這裏咱們使用其來隨機出一個矩形,作法是遍歷全部的矩形,用變量sumArea來計算當前遍歷過的全部矩形面積之和,而後變量area是當前遍歷的矩形的面積(注意這裏不是嚴格意義上的面積,而是該區域內整數座標的點的個數,因此長寬相乘的時候都要加1),而後咱們在當前全部矩形面積之和內隨機生成一個值,若是這個值小於area,那麼選擇當前的矩陣爲隨機矩形。這裏至關於一個大小爲area的水塘,在這個值以內的話,就更換selected。這個方法是沒啥問題,可是博主仍是沒想通爲啥不能直接隨機生成矩形的index。當咱們拿到隨機矩形後,以後就隨機出寬和高返回便可,參見代碼以下:code

 

解法一:orm

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

private:
    vector<vector<int>> _rects;
};

 

這道題在論壇上的主流解法實際上是這個,咱們用TreeMap來創建當前遍歷過的矩形面積之和跟該矩形位置之間的映射。而後當咱們求出全部的矩形面積之和後,咱們隨機生成一個值,而後在TreeMap中找到第一個大於這個值的矩形,這裏博主仍是有疑問,爲啥不能直接隨機矩形的位置,而是非要跟面積扯上關係。以後的步驟就跟上面的沒啥區別了,參見代碼以下:htm

 

解法二:blog

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

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 題目講解彙總(持續更新中...)

相關文章
相關標籤/搜索