夯实算法-非重叠矩形中的随机点

125 阅读2分钟

题目:非重叠矩形中的随机点

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

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

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

实现 Solution 类:

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

示例 1:

输入: ["Solution", "pick", "pick", "pick", "pick", "pick"]
[[[[-2, -2, 1, 1], [2, 2, 4, 6]]], [], [], [], [], []]
输出: [null, [1, -2], [1, -1], [-1, -2], [-2, -2], [0, 0]]

解释:
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<=1001 <= rects.length <= 100
  • rects[i].length==4rects[i].length == 4
  • 109 <=ai <xi <=109-10^9 <= ai < xi <= 10^9
  • 109 <=bi <yi <=109-10^9 <= bi < yi <= 10^9
  • xi - ai <= 2000
  • yi - bi <= 2000
  • 所有的矩形不重叠。
  • pick 最多被调用 10410^4 次。

解题思路

  • 矩形擀平连城一条线,随机这个线上的一个点,找到他对应原矩形的位置。
  • 找到这个点是第几个矩形的。
  • 这个点是这个矩形的第几个点,假设从左上角开始第一个是0
  • 算出这个点相对于左上角的行列位置

前缀和构造一个矩形点个数的数组,即nums[i]表示前i(i从1开始)个矩形的点的总个数; 对nums[n]进行random(),取出一个点的编号,在对nums进行二分查找,找到该点存在的矩形i; 在矩形i中进行随机取点,返回。

代码实现

int n;
int[] nums;
Random random;
int N;
int[][] rects;
public Solution(int[][] rects) {
    this.rects = rects;
    n = rects.length;
    nums = new int[n + 1];
    int i = 1;
    random = new Random();
    for (int[] r: rects) {
        int l = r[2] - r[0] + 1, w = r[3] - r[1] + 1;
        nums[i] = nums[i - 1] + l * w;
        i++;
    }
    N = nums[n];
}

public int[] pick() {
    int d = random.nextInt(N);
    int lo = 1, hi = n;
    while (lo < hi) {
        int m = (hi - lo) / 2 + lo;
        if (nums[m] < d) {
            lo = m + 1;
        } else {
            hi = m;
        }
    }
    int[] r = rects[lo - 1];
    int x = random.nextInt(r[2] - r[0] + 1) + r[0], y = random.nextInt(r[3] - r[1] + 1) + r[1];
    return new int[] {
        x, y
    };
}

运行结果

Snipaste_2023-04-26_23-33-41.png

复杂度分析

  • 空间复杂度:O(n)
  • 时间复杂度:O(n^2)

掘金(JUEJIN) 一起分享知识, Keep Learning!