Facebook Pixel

2249. Count Lattice Points Inside a Circle

MediumGeometryArrayHash TableMathEnumeration
Leetcode Link

Problem Description

You are given a 2D integer array circles where each element circles[i] = [xi, yi, ri] represents a circle on a grid. The circle has its center at coordinates (xi, yi) and has radius ri.

Your task is to count the total number of lattice points that are inside at least one of these circles.

A lattice point is simply a point that has integer coordinates (like (1, 2), (0, 0), (-3, 5), etc.).

Important notes:

  • If a point lies exactly on the circumference (boundary) of a circle, it counts as being inside that circle
  • A point only needs to be inside at least one circle to be counted (if it's inside multiple circles, it's still counted only once)
  • A point (x, y) is inside a circle with center (xi, yi) and radius ri if the distance from the point to the center is less than or equal to the radius, which can be checked using the formula: (x - xi)² + (y - yi)² ≤ ri²

For example, if you have a circle centered at (2, 2) with radius 2, the lattice points inside would include (2, 2) (the center), (2, 0) (on the boundary), (1, 1), (3, 3), and several others.

The solution iterates through all possible lattice points within the bounding box that could potentially be inside any circle (from (0, 0) to the maximum x and y coordinates that any circle could reach), checks if each point is inside at least one circle, and counts the total number of such points.

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

Intuition

The key insight is that we need to find all integer-coordinate points that fall inside at least one circle. Since we're dealing with integer coordinates, we can use a brute-force approach by checking every possible lattice point.

First, we need to determine the search space. We don't need to check infinite points - we only need to check points that could possibly be inside any of our circles. The furthest a circle can extend from the origin is when its center is at (x, y) with radius r, reaching up to x + r horizontally and y + r vertically. By finding the maximum extent across all circles, we establish our search boundary.

For each lattice point (i, j) in this bounded region, we check if it's inside any circle. To determine if a point is inside a circle, we use the distance formula. A point (i, j) is inside or on a circle with center (x, y) and radius r if the distance from the point to the center is at most r. Using the Pythagorean theorem, this translates to checking if (i - x)² + (j - y)² ≤ r².

The clever part of the solution is that once we find that a point is inside at least one circle, we can immediately count it and move on to the next point (using the break statement). We don't need to check the remaining circles for that point since we only care about whether it's inside at least one circle, not how many.

This brute-force approach works well when the circles are relatively small and the number of lattice points to check is manageable. The time complexity depends on the area covered by the circles rather than just the number of circles.

Learn more about Math patterns.

Solution Approach

The implementation follows a straightforward brute-force approach with three nested loops:

Step 1: Determine the search boundary

mx = max(x + r for x, _, r in circles)
my = max(y + r for _, y, r in circles)

We calculate the maximum x-coordinate (mx) and y-coordinate (my) that any circle can reach. This is done by finding the maximum value of x + r (rightmost point) and y + r (topmost point) across all circles. This ensures we check all points that could possibly be inside any circle.

Step 2: Iterate through all lattice points in the bounded region

for i in range(mx + 1):
    for j in range(my + 1):

We iterate through all integer coordinates from (0, 0) to (mx, my). The +1 in the range ensures we include the boundary points.

Step 3: Check if each point is inside any circle

for x, y, r in circles:
    dx, dy = i - x, j - y
    if dx * dx + dy * dy <= r * r:
        ans += 1
        break

For each lattice point (i, j), we check against all circles:

  • Calculate the horizontal distance dx = i - x and vertical distance dy = j - y from the point to the circle's center
  • Check if dx² + dy² ≤ r² (the squared distance is at most the squared radius)
  • If the point is inside or on the boundary of any circle, increment the counter and immediately break to avoid counting the same point multiple times

The algorithm efficiently counts each valid lattice point exactly once, returning the total count of all lattice points that are inside at least one circle.

The time complexity is O(mx × my × n) where n is the number of circles, and the space complexity is O(1) as we only use a counter variable.

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 simple example with circles = [[2, 2, 1], [3, 4, 1]].

Step 1: Determine search boundary

  • First circle: center (2, 2), radius 1 → can reach x = 2+1 = 3, y = 2+1 = 3
  • Second circle: center (3, 4), radius 1 → can reach x = 3+1 = 4, y = 4+1 = 5
  • Maximum bounds: mx = 4, my = 5

Step 2: Check each lattice point from (0,0) to (4,5)

Let's trace through some key points:

Point (2, 2):

  • Check circle 1: dx = 2-2 = 0, dy = 2-2 = 0
  • Distance² = 0² + 0² = 0 ≤ 1² ✓
  • Count = 1, break (no need to check circle 2)

Point (2, 3):

  • Check circle 1: dx = 2-2 = 0, dy = 3-2 = 1
  • Distance² = 0² + 1² = 1 ≤ 1² ✓
  • Count = 2, break

Point (3, 3):

  • Check circle 1: dx = 3-2 = 1, dy = 3-2 = 1
  • Distance² = 1² + 1² = 2 > 1² ✗
  • Check circle 2: dx = 3-3 = 0, dy = 3-4 = -1
  • Distance² = 0² + (-1)² = 1 ≤ 1² ✓
  • Count = 3, break

Point (0, 0):

  • Check circle 1: dx = 0-2 = -2, dy = 0-2 = -2
  • Distance² = (-2)² + (-2)² = 8 > 1² ✗
  • Check circle 2: dx = 0-3 = -3, dy = 0-4 = -4
  • Distance² = (-3)² + (-4)² = 25 > 1² ✗
  • Not inside any circle, skip

Continuing this process for all points in the grid, the lattice points inside at least one circle are:

  • Circle 1: (1,2), (2,1), (2,2), (2,3), (3,2)
  • Circle 2: (2,4), (3,3), (3,4), (3,5), (4,4)

Total unique points = 10 (points are counted only once even if they appear in multiple circles)

Solution Implementation

1class Solution:
2    def countLatticePoints(self, circles: List[List[int]]) -> int:
3        """
4        Count the number of integer lattice points that lie inside or on the boundary
5        of at least one circle.
6      
7        Args:
8            circles: List of circles, where each circle is [x_center, y_center, radius]
9      
10        Returns:
11            Number of unique lattice points covered by at least one circle
12        """
13        point_count = 0
14      
15        # Find the maximum x and y coordinates we need to check
16        # by finding the rightmost and topmost points any circle can reach
17        max_x = max(center_x + radius for center_x, _, radius in circles)
18        max_y = max(center_y + radius for _, center_y, radius in circles)
19      
20        # Iterate through all possible lattice points in the bounding rectangle
21        for x_coord in range(max_x + 1):
22            for y_coord in range(max_y + 1):
23                # Check if current point (x_coord, y_coord) is inside any circle
24                for center_x, center_y, radius in circles:
25                    # Calculate distance components from point to circle center
26                    delta_x = x_coord - center_x
27                    delta_y = y_coord - center_y
28                  
29                    # Check if point is inside or on the circle boundary
30                    # Using squared distances to avoid floating point operations
31                    if delta_x * delta_x + delta_y * delta_y <= radius * radius:
32                        point_count += 1
33                        break  # Point is covered, no need to check other circles
34      
35        return point_count
36
1class Solution {
2    public int countLatticePoints(int[][] circles) {
3        // Find the maximum x and y boundaries by checking all circles
4        // Each circle is represented as [centerX, centerY, radius]
5        int maxX = 0;
6        int maxY = 0;
7      
8        for (int[] circle : circles) {
9            // The rightmost point of a circle is centerX + radius
10            maxX = Math.max(maxX, circle[0] + circle[2]);
11            // The topmost point of a circle is centerY + radius
12            maxY = Math.max(maxY, circle[1] + circle[2]);
13        }
14      
15        // Count lattice points that fall within at least one circle
16        int count = 0;
17      
18        // Check each lattice point in the bounding rectangle
19        for (int x = 0; x <= maxX; x++) {
20            for (int y = 0; y <= maxY; y++) {
21                // Check if current point (x, y) is inside any circle
22                for (int[] circle : circles) {
23                    int centerX = circle[0];
24                    int centerY = circle[1];
25                    int radius = circle[2];
26                  
27                    // Calculate distance components from point to circle center
28                    int deltaX = x - centerX;
29                    int deltaY = y - centerY;
30                  
31                    // Check if point is inside or on the circle using distance formula
32                    // Point is inside if: (x - centerX)² + (y - centerY)² <= radius²
33                    if (deltaX * deltaX + deltaY * deltaY <= radius * radius) {
34                        count++;
35                        break; // Point found in at least one circle, no need to check others
36                    }
37                }
38            }
39        }
40      
41        return count;
42    }
43}
44
1class Solution {
2public:
3    int countLatticePoints(vector<vector<int>>& circles) {
4        // Find the maximum x and y coordinates to define our search boundary
5        // Each circle is represented as [centerX, centerY, radius]
6        int maxX = 0;
7        int maxY = 0;
8      
9        for (const auto& circle : circles) {
10            // The rightmost point of the circle is centerX + radius
11            maxX = max(maxX, circle[0] + circle[2]);
12            // The topmost point of the circle is centerY + radius
13            maxY = max(maxY, circle[1] + circle[2]);
14        }
15      
16        int latticePointCount = 0;
17      
18        // Iterate through all integer coordinates within the boundary
19        for (int x = 0; x <= maxX; ++x) {
20            for (int y = 0; y <= maxY; ++y) {
21                // Check if the current point (x, y) is inside or on any circle
22                for (const auto& circle : circles) {
23                    int centerX = circle[0];
24                    int centerY = circle[1];
25                    int radius = circle[2];
26                  
27                    // Calculate the distance components from the point to the circle center
28                    int deltaX = x - centerX;
29                    int deltaY = y - centerY;
30                  
31                    // Check if the point is inside or on the circle using distance formula
32                    // Point is inside/on circle if: (x - centerX)² + (y - centerY)² <= radius²
33                    if (deltaX * deltaX + deltaY * deltaY <= radius * radius) {
34                        ++latticePointCount;
35                        break;  // Point is counted once, no need to check other circles
36                    }
37                }
38            }
39        }
40      
41        return latticePointCount;
42    }
43};
44
1/**
2 * Counts the number of lattice points that lie inside or on the boundary of at least one circle.
3 * A lattice point is a point with integer coordinates.
4 * 
5 * @param circles - Array of circles, where each circle is [x, y, radius]
6 * @returns The count of lattice points covered by at least one circle
7 */
8function countLatticePoints(circles: number[][]): number {
9    // Find the maximum x and y boundaries to limit our search space
10    let maxX: number = 0;
11    let maxY: number = 0;
12  
13    // Calculate the rightmost and topmost points any circle can reach
14    for (const [centerX, centerY, radius] of circles) {
15        maxX = Math.max(maxX, centerX + radius);
16        maxY = Math.max(maxY, centerY + radius);
17    }
18  
19    let latticePointCount: number = 0;
20  
21    // Iterate through all possible lattice points in the bounded area
22    for (let x: number = 0; x <= maxX; ++x) {
23        for (let y: number = 0; y <= maxY; ++y) {
24            // Check if current point (x, y) is inside any circle
25            for (const [centerX, centerY, radius] of circles) {
26                // Calculate distance components from circle center to point
27                const deltaX: number = x - centerX;
28                const deltaY: number = y - centerY;
29              
30                // Check if point is inside or on the circle using distance formula
31                // Point is inside if distance² <= radius²
32                if (deltaX * deltaX + deltaY * deltaY <= radius * radius) {
33                    ++latticePointCount;
34                    break; // Point found in at least one circle, no need to check others
35                }
36            }
37        }
38    }
39  
40    return latticePointCount;
41}
42

Time and Space Complexity

Time Complexity: O(X * Y * n) where X is the maximum x-coordinate that needs to be checked (max of x + r across all circles), Y is the maximum y-coordinate that needs to be checked (max of y + r across all circles), and n is the number of circles.

  • The outer two loops iterate through all possible lattice points from (0, 0) to (mx, my), which gives us O(X * Y) iterations
  • For each lattice point, we iterate through all n circles to check if the point lies within any circle
  • The distance calculation dx * dx + dy * dy <= r * r is O(1)
  • In the worst case, we check all circles for each point before finding one that contains it (or determining none do)
  • Total: O(X * Y * n)

Space Complexity: O(1)

  • The algorithm uses only a constant amount of extra space
  • Variables ans, mx, my, i, j, x, y, r, dx, and dy all use O(1) space
  • No additional data structures are created that scale with input size
  • The input list circles is not counted as it's part of the input

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

Common Pitfalls

1. Forgetting to Consider Negative Coordinates

The current solution only checks points from (0, 0) to (max_x, max_y), which misses all lattice points in negative coordinate regions. If a circle is centered at (1, 1) with radius 3, it covers points like (-1, 0), (-2, 1), etc., which won't be counted.

Fix: Calculate both minimum and maximum bounds for x and y coordinates:

min_x = min(center_x - radius for center_x, _, radius in circles)
max_x = max(center_x + radius for center_x, _, radius in circles)
min_y = min(center_y - radius for _, center_y, radius in circles)
max_y = max(center_y + radius for _, center_y, radius in circles)

for x_coord in range(min_x, max_x + 1):
    for y_coord in range(min_y, max_y + 1):
        # ... rest of the logic

2. Integer Overflow in Distance Calculation

When calculating delta_x * delta_x + delta_y * delta_y, the multiplication can cause integer overflow for very large coordinate values or radii, leading to incorrect results.

Fix: Use careful bounds checking or consider using Python's unlimited precision integers (which is automatic in Python 3), or add explicit overflow checks in other languages.

3. Using Floating-Point Arithmetic

Some might be tempted to use sqrt((x-xi)² + (y-yi)²) <= r with floating-point square root, which can introduce precision errors and make boundary cases unreliable.

Fix: Always use squared distances as shown in the solution: dx * dx + dy * dy <= r * r to maintain integer arithmetic and avoid precision issues.

4. Not Breaking After Finding a Match

Forgetting the break statement after finding that a point is inside a circle would cause the same point to be counted multiple times if it's inside multiple circles.

Fix: Always include break after incrementing the counter to ensure each point is counted exactly once.

Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

Which of the following uses divide and conquer strategy?


Recommended Readings

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

Load More