2249. Count Lattice Points Inside a Circle
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 radiusri
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.
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 distancedy = 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 EvaluatorExample 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 usO(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
isO(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
, anddy
all useO(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.
Which of the following uses divide and conquer strategy?
Recommended Readings
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Want a Structured Path to Master System Design Too? Don’t Miss This!