Facebook Pixel

1828. Queries on Number of Points Inside a Circle

Problem Description

You have a set of points on a 2D plane and need to determine how many points fall within various circles.

Input:

  • points: An array where each element points[i] = [xi, yi] represents the coordinates of a point on a 2D plane. Multiple points can exist at the same coordinates.
  • queries: An array where each element queries[j] = [xj, yj, rj] defines a circle with center at (xj, yj) and radius rj.

Task: For each circle defined in queries, count how many points from the points array are inside or on the boundary of that circle.

Circle Inclusion Rule: A point (xi, yi) is considered inside a circle with center (xj, yj) and radius rj if the distance between the point and the center is less than or equal to the radius. Using the distance formula, this means: (xi - xj)² + (yi - yj)² ≤ rj²

Points that lie exactly on the circle's boundary (where the distance equals the radius) are counted as inside.

Output: Return an array answer where answer[j] contains the count of points inside the j-th circle.

Solution Approach: The solution iterates through each query (circle) and for each circle, checks every point to see if it falls within that circle. It uses the squared distance formula dx² + dy² ≤ r² to avoid computing square roots, where dx = point_x - circle_center_x and dy = point_y - circle_center_y. The count of points satisfying this condition is added to the result array.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

The most straightforward way to think about this problem is to check each point against each circle individually. Since we need to determine if a point is inside a circle, we naturally think of the geometric relationship between a point and a circle.

The key insight is recognizing that a point is inside or on a circle if its distance from the center is at most the radius. The distance formula between two points (x1, y1) and (x2, y2) is √((x1-x2)² + (y1-y2)²). So for a point to be inside a circle, we need: √((point_x - center_x)² + (point_y - center_y)²) ≤ radius

To avoid the computational cost of calculating square roots, we can square both sides of the inequality (since both sides are non-negative): (point_x - center_x)² + (point_y - center_y)² ≤ radius²

This gives us a simple condition to check without any expensive square root operations.

Since the problem asks for the count of points inside each circle independently, we can process each query separately. For each circle in queries, we iterate through all points and count how many satisfy our distance condition. This brute force approach works well when the number of points and queries is manageable.

The elegance of this solution lies in its simplicity - we're directly translating the geometric definition of "point inside circle" into code, optimizing only by avoiding square root calculations through algebraic manipulation.

Learn more about Math patterns.

Solution Approach

The solution uses a straightforward enumeration approach as mentioned in the reference. Here's how the implementation works:

Algorithm Structure:

  1. Initialize an empty result list ans to store the count for each query
  2. For each circle query (x, y, r):
    • Initialize a counter cnt to 0
    • For each point (i, j) in the points array:
      • Calculate the differences: dx = i - x and dy = j - y
      • Check if dx * dx + dy * dy <= r * r
      • If true, increment the counter (using cnt += condition which adds 1 when true, 0 when false)
    • Append the final count to the result list
  3. Return the result list

Key Implementation Details:

The code efficiently checks the distance condition using squared values:

dx, dy = i - x, j - y
cnt += dx * dx + dy * dy <= r * r

This line does two things:

  • Calculates the squared distance between point (i, j) and circle center (x, y)
  • Uses Python's boolean-to-integer conversion where True becomes 1 and False becomes 0, allowing us to directly add the comparison result to our counter

Time Complexity: O(n * m) where n is the number of points and m is the number of queries. For each query, we check all points.

Space Complexity: O(m) for storing the result array, where m is the number of queries. The algorithm uses only a constant amount of extra space beyond the output array.

The simplicity of this brute force approach makes it easy to understand and implement, while the optimization of using squared distances avoids any floating-point arithmetic or expensive square root operations.

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through a small example to illustrate the solution approach.

Given:

  • points = [[1, 3], [3, 3], [5, 3], [2, 2]]
  • queries = [[2, 3, 1], [4, 3, 1], [1, 1, 2]]

We need to find how many points fall inside or on each circle.

Query 1: Circle at (2, 3) with radius 1

Check each point:

  • Point [1, 3]:

    • dx = 1 - 2 = -1, dy = 3 - 3 = 0
    • dx² + dy² = 1 + 0 = 1 ≤ 1² = 1 ✓ (on boundary)
  • Point [3, 3]:

    • dx = 3 - 2 = 1, dy = 3 - 3 = 0
    • dx² + dy² = 1 + 0 = 1 ≤ 1 ✓ (on boundary)
  • Point [5, 3]:

    • dx = 5 - 2 = 3, dy = 3 - 3 = 0
    • dx² + dy² = 9 + 0 = 9 > 1 ✗ (outside)
  • Point [2, 2]:

    • dx = 2 - 2 = 0, dy = 2 - 3 = -1
    • dx² + dy² = 0 + 1 = 1 ≤ 1 ✓ (on boundary)

Count for Query 1: 3 points

Query 2: Circle at (4, 3) with radius 1

Check each point:

  • Point [1, 3]: dx² + dy² = 9 + 0 = 9 > 1
  • Point [3, 3]: dx² + dy² = 1 + 0 = 1 ≤ 1
  • Point [5, 3]: dx² + dy² = 1 + 0 = 1 ≤ 1
  • Point [2, 2]: dx² + dy² = 4 + 1 = 5 > 1

Count for Query 2: 2 points

Query 3: Circle at (1, 1) with radius 2

Check each point:

  • Point [1, 3]: dx² + dy² = 0 + 4 = 4 ≤ 4
  • Point [3, 3]: dx² + dy² = 4 + 4 = 8 > 4
  • Point [5, 3]: dx² + dy² = 16 + 4 = 20 > 4
  • Point [2, 2]: dx² + dy² = 1 + 1 = 2 ≤ 4

Count for Query 3: 2 points

Final Result: [3, 2, 2]

The algorithm systematically checks every point against every circle, using the squared distance formula to avoid computing square roots, making it both simple and efficient.

Solution Implementation

1class Solution:
2    def countPoints(self, points: List[List[int]], queries: List[List[int]]) -> List[int]:
3        """
4        Count the number of points inside or on the boundary of each query circle.
5      
6        Args:
7            points: List of 2D points represented as [x, y] coordinates
8            queries: List of circles represented as [center_x, center_y, radius]
9      
10        Returns:
11            List containing the count of points within each query circle
12        """
13        result = []
14      
15        # Process each query circle
16        for center_x, center_y, radius in queries:
17            point_count = 0
18          
19            # Check each point against the current circle
20            for point_x, point_y in points:
21                # Calculate the squared distance from point to circle center
22                distance_x = point_x - center_x
23                distance_y = point_y - center_y
24                squared_distance = distance_x * distance_x + distance_y * distance_y
25              
26                # Check if point is inside or on the circle boundary
27                # Using squared values to avoid floating point operations
28                if squared_distance <= radius * radius:
29                    point_count += 1
30          
31            # Add the count for this query to the result list
32            result.append(point_count)
33      
34        return result
35
1class Solution {
2    public int[] countPoints(int[][] points, int[][] queries) {
3        // Get the number of queries to process
4        int numQueries = queries.length;
5      
6        // Initialize result array to store count for each query
7        int[] result = new int[numQueries];
8      
9        // Process each query
10        for (int queryIndex = 0; queryIndex < numQueries; queryIndex++) {
11            // Extract circle center coordinates and radius from current query
12            int centerX = queries[queryIndex][0];
13            int centerY = queries[queryIndex][1];
14            int radius = queries[queryIndex][2];
15          
16            // Check each point to see if it lies within or on the circle
17            for (int[] point : points) {
18                // Extract point coordinates
19                int pointX = point[0];
20                int pointY = point[1];
21              
22                // Calculate the distance components between point and circle center
23                int deltaX = pointX - centerX;
24                int deltaY = pointY - centerY;
25              
26                // Check if point is within or on the circle using distance formula
27                // Compare squared distances to avoid sqrt calculation for efficiency
28                if (deltaX * deltaX + deltaY * deltaY <= radius * radius) {
29                    result[queryIndex]++;
30                }
31            }
32        }
33      
34        return result;
35    }
36}
37
1class Solution {
2public:
3    vector<int> countPoints(vector<vector<int>>& points, vector<vector<int>>& queries) {
4        vector<int> result;
5      
6        // Process each query circle
7        for (const auto& query : queries) {
8            int centerX = query[0];
9            int centerY = query[1];
10            int radius = query[2];
11          
12            int pointCount = 0;
13          
14            // Check each point to see if it lies within or on the circle
15            for (const auto& point : points) {
16                int pointX = point[0];
17                int pointY = point[1];
18              
19                // Calculate the squared distance from point to circle center
20                int deltaX = pointX - centerX;
21                int deltaY = pointY - centerY;
22                int squaredDistance = deltaX * deltaX + deltaY * deltaY;
23              
24                // Check if point is inside or on the circle boundary
25                // Using squared values to avoid floating point operations
26                if (squaredDistance <= radius * radius) {
27                    pointCount++;
28                }
29            }
30          
31            // Add the count for this query to the result
32            result.push_back(pointCount);
33        }
34      
35        return result;
36    }
37};
38
1/**
2 * Counts how many points fall within each query circle
3 * @param points - Array of 2D points where each point is [x, y]
4 * @param queries - Array of circles where each circle is [centerX, centerY, radius]
5 * @returns Array where each element represents the count of points within the corresponding query circle
6 */
7function countPoints(points: number[][], queries: number[][]): number[] {
8    // Process each query circle and count points within it
9    return queries.map(([centerX, centerY, radius]) => {
10        let pointCount = 0;
11      
12        // Check each point to see if it falls within the current circle
13        for (const [pointX, pointY] of points) {
14            // Calculate Euclidean distance between point and circle center
15            const distance = Math.sqrt(
16                Math.pow(centerX - pointX, 2) + Math.pow(centerY - pointY, 2)
17            );
18          
19            // Increment count if point is within or on the circle boundary
20            if (distance <= radius) {
21                pointCount++;
22            }
23        }
24      
25        return pointCount;
26    });
27}
28

Time and Space Complexity

The time complexity is O(m × n), where m is the length of the queries array and n is the length of the points array. This is because for each query (there are m queries), we iterate through all points (there are n points) to check if each point lies within the circle defined by the query. The distance calculation dx * dx + dy * dy <= r * r takes O(1) time for each point-query pair.

The space complexity is O(1) if we exclude the space used for the output array ans. The algorithm only uses a constant amount of extra space for variables like cnt, dx, and dy, which don't depend on the input size. If we include the output array, the space complexity would be O(m) since we store one result for each query.

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Integer Overflow in Distance Calculation

Problem: When calculating dx * dx + dy * dy, the multiplication can cause integer overflow in languages with fixed integer sizes (like C++ or Java). For example, if coordinates are near the maximum integer value, squaring them exceeds the integer limit.

Solution: Use appropriate data types that can handle larger values:

  • In C++/Java: Use long long or long for the distance calculations
  • In Python: This isn't an issue due to arbitrary precision integers, but be aware when porting code
# Safe approach in languages with overflow concerns:
# Cast to larger type before multiplication
squared_distance = long(dx) * long(dx) + long(dy) * long(dy)

2. Floating Point Precision Errors

Problem: Some developers might be tempted to use the actual distance formula with square roots:

# WRONG - can lead to precision errors
import math
distance = math.sqrt((point_x - center_x)**2 + (point_y - center_y)**2)
if distance <= radius:  # Precision issues here!
    point_count += 1

Solution: Always use squared distances to avoid floating point operations entirely:

# CORRECT - no floating point operations
if dx * dx + dy * dy <= radius * radius:
    point_count += 1

3. Boundary Point Handling

Problem: Misunderstanding whether points on the circle boundary should be included. The comparison operator matters:

  • Using < excludes boundary points (incorrect for this problem)
  • Using <= includes boundary points (correct)

Solution: Always use <= for this problem as specified:

# CORRECT - includes boundary points
if squared_distance <= radius * radius:
    point_count += 1

# WRONG - excludes boundary points
if squared_distance < radius * radius:
    point_count += 1

4. Coordinate System Assumptions

Problem: Assuming integer coordinates when the problem might allow floating-point coordinates, or vice versa. This affects both storage and comparison operations.

Solution: Check the problem constraints and handle accordingly:

# If coordinates can be floating point, ensure proper handling:
def countPoints(self, points: List[List[float]], queries: List[List[float]]) -> List[int]:
    # Use appropriate epsilon for floating point comparisons if needed
    EPSILON = 1e-9
    # But for this problem, squared distance comparison still works
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

Given a sorted array of integers and an integer called target, find the element that equals to the target and return its index. Select the correct code that fills the ___ in the given code snippet.

1def binary_search(arr, target):
2    left, right = 0, len(arr) - 1
3    while left ___ right:
4        mid = (left + right) // 2
5        if arr[mid] == target:
6            return mid
7        if arr[mid] < target:
8            ___ = mid + 1
9        else:
10            ___ = mid - 1
11    return -1
12
1public static int binarySearch(int[] arr, int target) {
2    int left = 0;
3    int right = arr.length - 1;
4
5    while (left ___ right) {
6        int mid = left + (right - left) / 2;
7        if (arr[mid] == target) return mid;
8        if (arr[mid] < target) {
9            ___ = mid + 1;
10        } else {
11            ___ = mid - 1;
12        }
13    }
14    return -1;
15}
16
1function binarySearch(arr, target) {
2    let left = 0;
3    let right = arr.length - 1;
4
5    while (left ___ right) {
6        let mid = left + Math.trunc((right - left) / 2);
7        if (arr[mid] == target) return mid;
8        if (arr[mid] < target) {
9            ___ = mid + 1;
10        } else {
11            ___ = mid - 1;
12        }
13    }
14    return -1;
15}
16

Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More