2249. Count Lattice Points Inside a Circle
Problem Description
The problem presents a scenario where multiple circles are drawn on a grid. Each circle is defined by its center point coordinates ( (x_i, y_i) ) and its radius ( r_i ). The task is to determine how many lattice points exist that fall inside at least one of these circles. A lattice point is a point on the grid with integer coordinates, and points lying exactly on the circumference of a circle are counted as inside that circle.
Intuition
To solve this problem, one straightforward approach is to check every possible point in the grid and determine whether it falls inside any of the circles. We do this by:
-
Identifying the largest possible x and y coordinates that we might need to check. This is determined by finding the maximum x plus radius and the maximum y plus radius from all the circles since a circle could potentially cover points to the right and above its center up to its radius.
-
We iterate through each point in this bounded grid space.
-
For each point, we calculate its distance from the center of every given circle using the distance formula ( (dx * dx + dy * dy) ). Here ( dx ) and ( dy ) are the differences in the x and y coordinates of the point and the circle's center, respectively. We compare this distance squared to the radius squared of the circle (since ( \sqrt{dx^2 + dy^2} <= r ) is equivalent to ( dx^2 + dy^2 <= r^2 )). This squared comparison avoids the use of a square root which is more computationally expensive.
-
If a point is inside any circle (including on the edge), we count it exactly once and then move on to the next point. If a point is not inside the current circle, we continue to check the next circle. Once a point is found inside a circle, there is no need to check the remaining circles which optimizes the process slightly.
-
Continue this process for all points, and then the
ans
variable will contain the total count of lattice points inside at least one circle.
Learn more about Math patterns.
Solution Approach
The implementation uses a brute force algorithm to solve the problem. Given the simplicity of checking whether a point is within a circle, there's no need for complex data structures or advanced patterns. The key steps are as follows:
-
First, we identify the maximum x-coordinate value (
mx
) and y-coordinate value (my
) that we might need to consider, which will be the bounds for our search space. This is accomplished using list comprehensions that iterate over all the circles and calculate the maximum x-coordinate plus the radius, and the maximum y-coordinate plus the radius, respectively. -
Then, we use two nested loops to iterate over every possible lattice point within these bounds. The outer loop runs across the x-coordinate range (from 0 to
mx
), and the inner loop runs across the y-coordinate range (from 0 tomy
). -
For each point
(i, j)
in our nested loops, the algorithm then iterates over every circle to check if the point lies within it. This is where the distance formula comes in. It computes the square of the distance from the point to the circle's center, given by the expressiondx * dx + dy * dy
wheredx = i - x
anddy = j - y
, and compares this with the square of the radius of the circler * r
. -
If at any point
dx * dx + dy * dy <= r * r
evaluates to true, we increment the count (stored in variableans
) by one and break out of the loop that iterates over the circles usingbreak
. This ensures we avoid double counting points that lie within multiple circles. -
Finally, after all points have been checked, the algorithm returns
ans
, which contains the total number of lattice points inside at least one circle.
This approach does not use any specific data structure optimizations; it's a direct application of mathematical principles combined with iterative brute force checking. The efficiency could potentially be improved by reducing the search space or by using a geometric data structure to minimize the number of distance checks required, but the given solution is straightforward and relies on the computation being inexpensive enough to check all points within reasonable bounds.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's consider a small example with two circles to demonstrate how the solution works:
-
Suppose we have two circles, ( C_1 ) with center at ( (x_1, y_1) = (2, 3) ) and radius ( r_1 = 2 ), and ( C_2 ) with center at ( (x_2, y_2) = (5, 5) ) and radius ( r_2 = 1 ).
-
Based on the circles' centers and radii, the maximum x-coordinates we'll need to check is ( x_1 + r_1 = 2 + 2 = 4 ) and ( x_2 + r_2 = 5 + 1 = 6 ). Therefore, the maximum x-coordinate (
mx
) to consider is 6. Similarly, for the y-coordinates, we have ( y_1 + r_1 = 3 + 2 = 5 ) and ( y_2 + r_2 = 5 + 1 = 6 ). Hence, the maximum y-coordinate (my
) to check is 6. -
Now, we'll iterate through all lattice points within the bounded space. We start with point (0,0) and end at point (6,6). For illustration, let's check some points to see if they fall inside any circle:
-
Take the point (2,2). For ( C_1 ), we calculate ( dx = 2 - 2 = 0 ) and ( dy = 2 - 3 = -1 ). The distance squared is ( dx^2 + dy^2 = 0^2 + (-1)^2 = 1 ), which is less than ( r_1^2 = 4 ), so the point is inside ( C_1 ). We count it and move to the next point.
-
Consider the point (5,4). For ( C_1 ), ( dx = 5 - 2 = 3 ) and ( dy = 4 - 3 = 1 ) giving us ( dx^2 + dy^2 = 3^2 + 1^2 = 10 ), which is greater than ( r_1^2 = 4 ), so it's outside ( C_1 ). For ( C_2 ), ( dx = 5 - 5 = 0 ) and ( dy = 4 - 5 = -1 ), yielding ( dx^2 + dy^2 = 0^2 + (-1)^2 = 1 ), which is less than ( r_2^2 = 1 ), making the point inside ( C_2 ). We count it.
-
-
We continue this process, incrementing our count each time we find a point within any circle.
-
After completing the iteration over all points, let’s say our counter
ans
stands at 20. This means there are 20 lattice points that lie within at least one of the circles provided.
This example takes only a small portion of the grid and a couple of circles to illustrate the solution steps in an easily understandable manner. In practice, the iteration would cover a larger set of points and potentially more circles, but the principle remains exactly the same.
Solution Implementation
1from typing import List
2
3class Solution:
4 def countLatticePoints(self, circles: List[List[int]]) -> int:
5 # Initialize a counter for lattice points
6 count = 0
7
8 # Calculate the maximum x and y coordinates to consider, so the iteration does not go beyond necessary
9 max_x = max(x + r for x, _, r in circles)
10 max_y = max(y + r for _, y, r in circles)
11
12 # Iterate over all the points within the area defined by max_x and max_y
13 for i in range(max_x + 1):
14 for j in range(max_y + 1):
15 # Check if the current point (i, j) lies within any of the given circles
16 for x, y, radius in circles:
17 # Calculate the squared distance from the center of the circle (x, y) to the point (i, j)
18 dx, dy = i - x, j - y
19 if dx * dx + dy * dy <= radius * radius:
20 # If the point is within a circle, increment the counter and move to the next point
21 count += 1
22 break # Important to avoid counting a point multiple times
23 # Return the total count of lattice points within all circles
24 return count
25
1class Solution {
2
3 // This method counts all the lattice points that are inside or on the perimeter of the given circles.
4 // Each circle is represented by an array with three integers: [x_center, y_center, radius].
5 public int countLatticePoints(int[][] circles) {
6 // 'maxX' and 'maxY' are used to determine the size of the grid to check for lattice points.
7 int maxX = 0, maxY = 0;
8
9 // Calculate the furthest x and y coordinates that we need to check, by looking at the circle
10 // with the largest x + radius and y + radius.
11 for (var circle : circles) {
12 maxX = Math.max(maxX, circle[0] + circle[2]);
13 maxY = Math.max(maxY, circle[1] + circle[2]);
14 }
15
16 // 'count' will store the total number of lattice points.
17 int count = 0;
18
19 // Check each point in the grid.
20 for (int x = 0; x <= maxX; ++x) {
21 for (int y = 0; y <= maxY; ++y) {
22 // Check if this point is within or on any of the circles.
23 for (var circle : circles) {
24 int deltaX = x - circle[0];
25 int deltaY = y - circle[1];
26 // Check if the point (x, y) is inside the circle by comparing the square of the distance
27 // from (x, y) to the circle's center with the square of the circle's radius.
28 if (deltaX * deltaX + deltaY * deltaY <= circle[2] * circle[2]) {
29 // If the point is in the circle, increment the count and move to the next point.
30 ++count;
31 break; // Move to the next point since we only need to count each point once.
32 }
33 }
34 }
35 }
36
37 // Return the total count of lattice points.
38 return count;
39 }
40}
41
1#include <vector>
2#include <algorithm>
3
4class Solution {
5public:
6 int countLatticePoints(vector<vector<int>>& circles) {
7 int maxX = 0, maxY = 0;
8
9 // Find the maximum x and y values to limit the search space
10 for (auto& circle : circles) {
11 maxX = max(maxX, circle[0] + circle[2]);
12 maxY = max(maxY, circle[1] + circle[2]);
13 }
14
15 int answer = 0; // Initialize count of lattice points
16
17 // Iterate over the bounded search area
18 for (int x = 0; x <= maxX; ++x) {
19 for (int y = 0; y <= maxY; ++y) {
20 // Check every circle to see if the point is inside it
21 for (auto& circle : circles) {
22 int deltaX = x - circle[0]; // Difference in x
23 int deltaY = y - circle[1]; // Difference in y
24
25 // Check if the point (x, y) is within the current circle
26 if (deltaX * deltaX + deltaY * deltaY <= circle[2] * circle[2]) {
27 ++answer; // Increment the count if inside any circle
28 break; // Only count once, even if within multiple circles
29 }
30 }
31 }
32 }
33
34 return answer; // Return the total count of lattice points
35 }
36};
37
1function countLatticePoints(circles: number[][]): number {
2 // Initialize maximum x and y values to track the furthest points
3 let maxX = 0;
4 let maxY = 0;
5
6 // Determine the maximum x and y values considering all circles
7 for (const [cx, cy, radius] of circles) {
8 maxX = Math.max(maxX, cx + radius);
9 maxY = Math.max(maxY, cy + radius);
10 }
11
12 // Initialize the answer variable to count lattice points
13 let latticePointCount = 0;
14
15 // Iterate over all possible lattice points within the calculated bounds
16 for (let x = 0; x <= maxX; ++x) {
17 for (let y = 0; y <= maxY; ++y) {
18 // Check if current point (x, y) lies within any of the circles
19 for (const [cx, cy, radius] of circles) {
20 const deltaX = x - cx;
21 const deltaY = y - cy;
22 // If point is within the circle, increment the count and break out of the loop
23 if (deltaX * deltaX + deltaY * deltaY <= radius * radius) {
24 latticePointCount++;
25 break;
26 }
27 }
28 }
29 }
30
31 // Return the total count of lattice points within all circles
32 return latticePointCount;
33}
34
Time and Space Complexity
The given code snippet is designed to count all the lattice points (points with integer coordinates) that lie within or on the boundary of given circles. Each circle is represented by its center coordinates and its radius. The code does the following:
- Calculates the maximum x and y coordinates (
mx
andmy
) that need to be checked based on the sum of the x or y coordinate of a circle's center and its radius. This determines the bounding box within which lattice points could potentially lie inside a circle. - It then iterates over all integer points within this bounding box using two nested loops. For each point
(i, j)
, it checks if the point lies inside any of the circles by calculating the distance from the point to the center of each circle and comparing it with the radius of the circle. - If the point is inside a circle, the count (
ans
) is incremented by 1, and the innermost loop is broken to avoid counting a point more than once if it lies within multiple circles.
Time Complexity:
The time complexity is determined by the number of iterations in the nested loops.
- The outer loop runs
mx + 1
times and the second loop runsmy + 1
times, giving(mx + 1) * (my + 1)
for the two combined. - The innermost loop runs for each circle, so if there are
n
circles, it runsn
times for each point.
Therefore, the time complexity is O(n * (mx + 1) * (my + 1))
, where n
is the number of circles, mx
is the maximum x-coordinate to be considered, and my
is the maximum y-coordinate to be considered.
Space Complexity:
The space complexity of the code is O(1)
. The only extra space used is a handful of variables for keeping track of counts and iterating through loops, such as ans
, mx
, my
, dx
, dy
. These require a fixed amount of space that doesn't change with the input size (number of circles, size of coordinates, or radii of the circles).
Learn more about how to find time and space complexity quickly using problem constraints.
Which data structure is used to implement recursion?
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
LeetCode 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 we
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 algomonster s3 us east 2 amazonaws com recursion jpg You first
Want a Structured Path to Master System Design Too? Don’t Miss This!