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)};
    }
    
    
}

posted @ 2020-12-09 03:03  EvanMeetTheWorld  阅读(20)  评论(0)    收藏  举报