LeetCode 497 Random Point in Non-overlapping Rectangles(TreeMap)
it is another design related problem.
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.
pay attention: 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.
就是说 给出一些长方形 长方形之间不重叠,从这些长方形组成的大区域内随机选点。注意选择的点是integer的点。
class Solution {
public Solution(int[][] rects) {
}
public int[] pick() {
}
}
我能想到的就是找出这些长方形的上界 下界 左右边界,然后随机取点,然后要判断这些点否在任何一个矩形内。在的话就直接返回,不在的话就重新random一个。
判断是不是在矩形里面用的方法就是遍历rects。
根据这种想法 我写出以下代码,但是有错误:NullPointerException
class Solution {
int minX;
int maxX;
int minY;
int maxY;
int[][] rects;
Random randX;
Random randY;
public Solution(int[][] rects) {
rects = rects; --->这儿错了
randX = new Random();
randY = new Random();
minY = Integer.MAX_VALUE;
minX = Integer.MAX_VALUE;
maxY = Integer.MIN_VALUE;
maxY = Integer.MIN_VALUE;
for (int[] rect: rects) {
System.out.println(Arrays.toString(rect));
minX = Math.min(minX, rect[0]);
minY = Math.min(minY, rect[1]);
maxX = Math.max(maxX, rect[2]);
maxY = Math.max(maxY, rect[3]);
}
}
public int[] pick() {
//pick any num from [minX, maxX]
//and [minY, maxY]
int x = randX.nextInt(maxX - minX + 1) + minX;
int y = randY.nextInt(maxY - minY + 1) + minY;
while (outOfRange(x, y)) {
x = randX.nextInt(maxX - minX + 1) + minX;
y = randY.nextInt(maxY - minY + 1) + minY;
}
return new int[]{x, y};
}
private boolean outOfRange(int x, int y) {
for (int[] rect: rects) { ======================>>>>>>>> this is the part that went wrong.
if (rect[0] <= x && x <= rect[2] && rect[1] <= y && y <= rect[3]) {
return true;
}
}
return false;
}
}
找到了问题 但是仍然解决不了代码写的像屎一样这个事实 而且还TLE
看了看solution,发现这是一道TreeMap的问题
class Solution {
TreeMap<Integer, Integer> map;
int[][] arrays;
int sum;
Random rand;
public Solution(int[][] rects) {
arrays = rects;
map = new TreeMap<>();
sum = 0;
rand = new Random();
for (int i = 0; i < rects.length; i++) {
int[] rect = rects[i];
sum += (rect[2] - rect[0] + 1) * (rect[3] - rect[1] + 1);
map.put(sum, i); //sum is the prefix area of each rectangle, and i is the ith rect
}
}
public int[] pick() {
int c = map.ceilingKey(rand.nextInt(sum) + 1);
//找到大于等于rand.nextInt(sum)+1的最小的key->就是说在【0, sum】中取个任意值 然后找这个Map中第一个大于等于的这个key(最接近的)
return pickInRect(arrays[map.get(c)]); //pick this rect
}
private int[] pickInRect(int[] rect) { //and get a random point within this rect
int left = rect[0], right = rect[2], bot = rect[1], top = rect[3];
return new int[]{left + rand.nextInt(right - left + 1), bot + rand.nextInt(top - bot + 1)};
}
}

浙公网安备 33010602011771号