Talentd
FleetCode
Make and follow sheets.Sign in

Random Point in Non-overlapping Rectangles solution and explanation

MediumArrayBinary SearchMathOrdered Set5 min read40.8% acceptanceUpdated 9 Apr 2026
Random Point in Non-overlapping Rectangles | LeetCode 497 | C++, PythonKnowledge Center · 26:35 · 6K viewsWatch on YouTube
9 more videos on this problem
  1. Random Point in Non-overlapping Rectangles | LeetCode 497 | C++, PythonKnowledge Center · 26:35 · 6K views
  2. random point in non overlapping rectangles leetcode | leetcode 497Naresh Gupta · 8:55 · 2K views
  3. Random Point in Non-overlapping Rectangles | Leet code 497 | Theory explained + Python codeSai Anish Malla · 16:35 · 816 views
  4. Random Point in Non-overlapping Rectangles | Day 22 | [ August LeetCoding ] [ Leetcode #497 ]Algorithms Made Easy · 4:12 · 784 views
  5. Leetcode - Random Point in Non-overlapping Rectangles (Python)Timothy H Chang · 6:28 · 670 views
  6. Random Point in Non-overlapping Rectangles LeetCode August ChallengeSM TechWorld · 20:00 · 533 views
  7. 【每日一题】497. Random Point in Non-overlapping Rectangles, 11/02/2019Huifeng Guan · 24:21 · 528 views
  8. Daily Leetcode #144: Aug 22, 2020 - 497. Random Point in Non-overlapping RectanglesProgramming Live with Larry · 10:04 · 517 views
  9. Leetcode [497] Random Point in Non-overlapping RectanglesSDE Skills · 34:49 · 383 views
  10. Random Point In Non Overlapping Rectangles | Leetcode August Challenge Day 22 | Leetcode 497Coding Decoded · 8:15 · 375 views

The problem

You are given an array of non-overlapping axis-aligned rectangles rects where rects[i] = [ai, bi, xi, yi] indicates that (ai, bi) is the bottom-left corner point of the ith rectangle and (xi, yi) is the top-right corner point of the ith rectangle. Design an algorithm to pick a random integer point inside the space covered by one of the given rectangles. A point on the perimeter of a rectangle is included in the space covered by the rectangle.

Any integer point inside the space covered by one of the given rectangles should be equally likely to be returned.

Note that an integer point is a point that has integer coordinates.

Implement the Solution class:

  • Solution(int[][] rects) Initializes the object with the given rectangles rects.
  • int[] pick() Returns a random integer point [u, v] inside the space covered by one of the given rectangles.

Example 1:

Input
["Solution", "pick", "pick", "pick", "pick", "pick"]
[[[[-2, -2, 1, 1], [2, 2, 4, 6]]], [], [], [], [], []]
Output
[null, [1, -2], [1, -1], [-1, -2], [-2, -2], [0, 0]]

Explanation
Solution solution = new Solution([[-2, -2, 1, 1], [2, 2, 4, 6]]);
solution.pick(); // return [1, -2]
solution.pick(); // return [1, -1]
solution.pick(); // return [-1, -2]
solution.pick(); // return [-2, -2]
solution.pick(); // return [0, 0]

Constraints:

  • 1 <= rects.length <= 100
  • rects[i].length == 4
  • -109 <= ai < xi <= 109
  • -109 <= bi < yi <= 109
  • xi - ai <= 2000
  • yi - bi <= 2000
  • All the rectangles do not overlap.
  • At most 104 calls will be made to pick.

Approach overview

Problem Overview: You are given several axis-aligned rectangles that do not overlap. Each call to pick() must return a random integer point from the union of these rectangles, where every valid point across all rectangles has equal probability.

Approach 1: Weighted Rectangle Selection Using Prefix Sum (Initialization: O(n), Pick: O(log n), Space: O(n))

Each rectangle contributes a number of integer points equal to (x2 - x1 + 1) * (y2 - y1 + 1). Treat rectangles as weighted buckets where the weight equals the number of points inside it. Build a prefix sum array of these areas during initialization. When pick() runs, generate a random integer in the range [1, totalPoints] and locate the rectangle containing that index using binary search. After selecting the rectangle, generate two random coordinates inside its bounds to produce the final point. This guarantees uniform probability across all integer points while keeping each pick efficient.

Approach 2: Uniform Randomized Area Selection (Initialization: O(n), Pick: O(n), Space: O(n))

This approach also computes the number of integer points inside each rectangle and stores cumulative areas. Instead of binary searching, you iterate through rectangles subtracting their area until the random index falls within a rectangle’s range. Once the rectangle is identified, generate random x and y coordinates within its bounds. The logic is simple and easy to implement, but rectangle lookup becomes linear. The technique still relies on uniform randomized sampling over total area.

Recommended for interviews: The prefix sum + binary search approach is the expected solution. It demonstrates understanding of weighted random sampling, array preprocessing, and efficient lookup. A linear scan works but scales poorly when pick() is called many times. Showing the brute logic first and then optimizing with prefix sums signals strong problem-solving skills.

Approach 1: Weighted Rectangle Selection Using Prefix Sum

This approach involves calculating the area (number of integer points) of each rectangle and using a prefix sum array to randomly select a rectangle based on these areas. After selecting a rectangle, a random point within that rectangle is generated.

import random

class Solution:
    def __init__(self, rects: List[List[int]]):
        self.rects = rects
        self.points = [0]
        for a, b, x, y in rects:
            self.points.append(self.points[-1] + (x - a + 1) * (y - b + 1))

    def pick(self) -> List[int]:
        random_point = random.randint(0, self.points[-1] - 1)
        rectangle_index = bisect.bisect_right(self.points, random_point) - 1
        a, b, x, y = self.rects[rectangle_index]
        width = x - a + 1
        height = y - b + 1
        base_in_rectangle = random_point - self.points[rectangle_index]
        dx = base_in_rectangle % width
        dy = base_in_rectangle // width
        return [a + dx, b + dy]
import java.util.*;

class Solution {
    int[] points;
    int[][] rects;
    Random rand;

    public Solution(int[][] rects) {
        this.rects = rects;
        this.points = new int[rects.length + 1];
        for (int i = 0; i < rects.length; i++) {
            int a = rects[i][0], b = rects[i][1], x = rects[i][2], y = rects[i][3];
            points[i + 1] = points[i] + (x - a + 1) * (y - b + 1);
        }
        rand = new Random();
    }

    public int[] pick() {
        int randPoint = rand.nextInt(points[rects.length]);
        int idx = Arrays.binarySearch(points, randPoint + 1) - 1;
        int[] rect = rects[idx];
        int a = rect[0], b = rect[1];
        int width = rect[2] - a + 1;
        int withinRect = randPoint - points[idx];
        int dx = withinRect % width;
        int dy = withinRect / width;
        return new int[] { a + dx, b + dy };
    }
}
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <numeric>
using namespace std;

class Solution {
    vector<vector<int>> rects;
    vector<int> points;
public:
    Solution(vector<vector<int>>& rects) : rects(rects) {
        points.push_back(0);
        for (auto& rect : rects) {
            int a = rect[0], b = rect[1], x = rect[2], y = rect[3];
            points.push_back(points.back() + (x - a + 1) * (y - b + 1));
        }
    }

    vector<int> pick() {
        int rand_point = rand() % points.back();
        int idx = upper_bound(points.begin(), points.end(), rand_point) - points.begin() - 1;
        auto rect = rects[idx];
        int a = rect[0], b = rect[1];
        int width = rect[2] - a + 1;
        int within_rect = rand_point - points[idx];
        int dx = within_rect % width;
        int dy = within_rect / width;
        return {a + dx, b + dy};
    }
};
class Solution {
  constructor(rects) {
    this.rects = rects;
    this.points = [0];
    for (let rect of rects) {
      const [a, b, x, y] = rect;
      this.points.push(this.points[this.points.length - 1] + (x - a + 1) * (y - b + 1));
    }
  }

  pick() {
    let rand_point = Math.floor(Math.random() * this.points[this.points.length - 1]);
    let idx = this.points.findIndex(p => p > rand_point) - 1;
    const [a, b, x, y] = this.rects[idx];
    const width = x - a + 1;
    const within_rect = rand_point - this.points[idx];
    const dx = within_rect % width;
    const dy = Math.floor(within_rect / width);
    return [a + dx, b + dy];
  }
}

In this implementation, we calculate the total number of integer points for each rectangle and build up a prefix sum array. When picking a point, a random index is generated and used to determine which rectangle the point falls into using binary search. A specific point within this rectangle is then selected by calculating its relative coordinates.

Complexity

Time Complexity: O(log n) for picking a point due to binary search, where n is the number of rectangles.
Space Complexity: O(n) for storing prefix sums, where n is the number of rectangles.

Try this approach in the editor

Approach 2: Uniform Randomized Area Selection

In this approach, a hash map is used to store all possible integer point coordinates in rectangles. A random point is accessed directly by randomly selecting a key from the hash map. However, this solution is not optimal due to time and space requirements.

import random

class Solution:
    def __init__(self, rects):
        self.points_map = {}
        self.total_points = 0
        for a, b, x, y in rects:
            for i in range(a, x + 1):
                for j in range(b, y + 1):
                    self.points_map[self.total_points] = (i, j)
                    self.total_points += 1

    def pick(self):
        pick_index = random.randint(0, self.total_points - 1)
        return self.points_map[pick_index]
#include <map>
#include <vector>
#include <cstdlib>
using namespace std;

class Solution {
    map<int, pair<int, int>> points_map;
    int totalPoints = 0;
public:
    Solution(vector<vector<int>>& rects) {
        for (auto& rect : rects) {
            int a = rect[0], b = rect[1], x = rect[2], y = rect[3];
            for (int i = a; i <= x; ++i) {
                for (int j = b; j <= y; ++j) {
                    points_map[totalPoints++] = {i, j};
                }
            }
        }
    }

    vector<int> pick() {
        int pickIndex = rand() % totalPoints;
        return {points_map[pickIndex].first, points_map[pickIndex].second};
    }
};

This Python solution precomputes every possible point across all rectangles into a hash map. When picking, it simply picks one key directly from the hash map, which leads to high memory usage and unwieldy initialization.

Complexity

Time Complexity: O(1) for picking, assuming map insertion and access time is constant.
Space Complexity: O(m*n), where m and n are the width and height of the largest rectangle.

Try this approach in the editor

Approach 3: Default Approach

type Solution struct {
	s     []int
	rects [][]int
}

func Constructor(rects [][]int) Solution {
	n := len(rects)
	s := make([]int, n+1)
	for i, v := range rects {
		s[i+1] = s[i] + (v[2]-v[0]+1)*(v[3]-v[1]+1)
	}
	return Solution{s, rects}
}

func (this *Solution) Pick() []int {
	n := len(this.rects)
	v := 1 + rand.Intn(this.s[len(this.s)-1])
	left, right := 0, n
	for left < right {
		mid := (left + right) >> 1
		if this.s[mid] >= v {
			right = mid
		} else {
			left = mid + 1
		}
	}
	rect := this.rects[left-1]
	x, y := rect[0]+rand.Intn(rect[2]-rect[0]+1), rect[1]+rand.Intn(rect[3]-rect[1]+1)
	return []int{x, y}
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
Weighted Rectangle Selection Using Prefix Sum

Time Complexity: O(log n) for picking a point due to binary search, where n is the number of rectangles.
Space Complexity: O(n) for storing prefix sums, where n is the number of rectangles.

Uniform Randomized Area Selection

Time Complexity: O(1) for picking, assuming map insertion and access time is constant.
Space Complexity: O(m*n), where m and n are the width and height of the largest rectangle.

Default Approach–

Complexity analysis

ApproachTimeSpaceWhen to Use
Weighted Rectangle Selection Using Prefix SumInit: O(n), Pick: O(log n)O(n)Best general solution when pick() is called frequently
Uniform Randomized Area Selection (Linear Scan)Init: O(n), Pick: O(n)O(n)Simpler implementation when number of rectangles is small

Frequently asked questions

Is Random Point in Non-overlapping Rectangles easy or hard?

The problem is rated Medium because the key challenge is recognizing it as a weighted random sampling problem. Once the idea of mapping rectangle area to probability is clear, prefix sums and binary search provide a clean and efficient implementation.

Random Point in Non-overlapping Rectangles Python/Java solution

Implement a class that stores rectangles and a prefix sum of their areas. During pick(), generate a random integer within the total area, binary search the prefix array to locate the rectangle, and randomly select x and y coordinates within that rectangle. The same logic works across Python, Java, C++, and JavaScript.

How to solve Random Point in Non-overlapping Rectangles in O(n)?

An O(n) per-pick approach generates a random number within the total area and linearly scans rectangles until the corresponding cumulative area range is found. After selecting the rectangle, random x and y coordinates are generated inside its bounds. Initialization still takes O(n).

What is the best approach for Random Point in Non-overlapping Rectangles?

The most efficient solution uses weighted rectangle selection with a prefix sum array and binary search. Each rectangle is weighted by the number of integer points it contains. A random index across the total area is generated, and binary search finds the corresponding rectangle in O(log n) time.

Is Random Point in Non-overlapping Rectangles asked at Google/Amazon/Meta?

Random sampling and weighted probability problems appear frequently in interviews at companies like Google, Amazon, and Meta. Variants involving weighted random selection, prefix sums, or reservoir sampling are commonly tested in system design and algorithm rounds.

What data structure is used in Random Point in Non-overlapping Rectangles?

The main data structure is an array storing prefix sums of rectangle areas. This allows mapping a random index to a rectangle efficiently using binary search. The rectangles themselves are stored in an array for constant-time coordinate generation.

What is the time complexity of Random Point in Non-overlapping Rectangles?

Building the prefix sum array takes O(n) time during initialization. Each call to pick() runs in O(log n) using binary search to locate the rectangle, followed by O(1) random coordinate generation. Space complexity is O(n) for storing cumulative areas.

Comments

Now write it yourselfClose this page and solve Random Point in Non-overlapping Rectangles in the editor, without looking.
Practise Random Point in Non-overlapping Rectangles