Taro Logo

Circle and Rectangle Overlapping

Medium
Asked by:
Profile picture
Profile picture
17 views
Topics:
Arrays

You are given a circle represented as (radius, xCenter, yCenter) and an axis-aligned rectangle represented as (x1, y1, x2, y2), where (x1, y1) are the coordinates of the bottom-left corner, and (x2, y2) are the coordinates of the top-right corner of the rectangle.

Return true if the circle and rectangle are overlapped otherwise return false. In other words, check if there is any point (xi, yi) that belongs to the circle and the rectangle at the same time.

Example 1:

Input: radius = 1, xCenter = 0, yCenter = 0, x1 = 1, y1 = -1, x2 = 3, y2 = 1
Output: true
Explanation: Circle and rectangle share the point (1,0).

Example 2:

Input: radius = 1, xCenter = 1, yCenter = 1, x1 = 1, y1 = -3, x2 = 2, y2 = -1
Output: false

Example 3:

Input: radius = 1, xCenter = 0, yCenter = 0, x1 = -1, y1 = 0, x2 = 0, y2 = 1
Output: true

Constraints:

  • 1 <= radius <= 2000
  • -104 <= xCenter, yCenter <= 104
  • -104 <= x1 < x2 <= 104
  • -104 <= y1 < y2 <= 104

Solution


Clarifying Questions

When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:

  1. What are the data types and ranges for the circle's center coordinates (x, y) and radius? Are they integers or floating-point numbers?
  2. What are the data types and ranges for the rectangle's coordinates (x1, y1, x2, y2), and how are they oriented? Is it guaranteed that x1 < x2 and y1 < y2?
  3. If the circle and rectangle only touch at a single point (e.g., tangent), should that be considered an overlap?
  4. Can the radius of the circle be zero? What if the rectangle has zero area (e.g., a line or a point)?
  5. What output should I return if there is an overlap? True/False, 1/0, or something else?

Brute Force Solution

Approach

The brute force approach to checking if a circle and rectangle overlap involves carefully checking every possible scenario to see if they intersect. We essentially see if any part of the circle falls inside the rectangle, or vice versa, by considering many individual points.

Here's how the algorithm would work step-by-step:

  1. Imagine the circle is actually made up of a huge number of very small points that completely fill the circle's area.
  2. For each of these tiny points, check if that point is located inside the rectangle.
  3. If even a single one of these points is inside the rectangle, then the circle and rectangle overlap.
  4. Next, imagine the rectangle is also made up of a huge number of very small points that completely fill the rectangle's area.
  5. For each of these rectangle points, check if that point is located inside the circle.
  6. If any one of these points from the rectangle is inside the circle, then the circle and rectangle overlap.
  7. If either of the above scenarios is true, then the circle and rectangle are overlapping. If neither is true, they are not.

Code Implementation

def circle_and_rectangle_overlapping_brute_force(circle_center_x,
                                                     circle_center_y,
                                                     circle_radius,
                                                     rectangle_bottom_left_x,
                                                     rectangle_bottom_left_y,
                                                     rectangle_top_right_x,
                                                     rectangle_top_right_y):

    number_of_sample_points = 100

    # Check if any point on the circle is inside the rectangle
    for angle in range(number_of_sample_points):
        angle_in_radians = 2 * 3.14159 * angle / number_of_sample_points
        point_x = circle_center_x + circle_radius * cos(angle_in_radians)
        point_y = circle_center_y + circle_radius * sin(angle_in_radians)

        if rectangle_bottom_left_x <= point_x <= rectangle_top_right_x and \
           rectangle_bottom_left_y <= point_y <= rectangle_top_right_y:
            return True

    # Check if any point on the rectangle is inside the circle
    # We sample points on the rectangle's perimeter to improve performance
    for x in range(rectangle_bottom_left_x, rectangle_top_right_x + 1):
        if (x - circle_center_x)**2 + (rectangle_bottom_left_y - circle_center_y)**2 <= circle_radius**2:
            return True
        if (x - circle_center_x)**2 + (rectangle_top_right_y - circle_center_y)**2 <= circle_radius**2:
            return True

    # Next, check the vertical sides of the rectangle
    for y in range(rectangle_bottom_left_y, rectangle_top_right_y + 1):
        if (rectangle_bottom_left_x - circle_center_x)**2 + (y - circle_center_y)**2 <= circle_radius**2:
            return True
        if (rectangle_top_right_x - circle_center_x)**2 + (y - circle_center_y)**2 <= circle_radius**2:
            return True

    return False

def cos(x):
    return __import__('math').cos(x)

def sin(x):
    return __import__('math').sin(x)

Big(O) Analysis

Time Complexity
O(infinity)The described brute force solution conceptually involves checking an infinite number of points within the circle against the rectangle and vice versa. Since we are checking all possible points, the number of operations grows towards infinity as we consider smaller and smaller points to check. Therefore, the time complexity can be expressed as O(infinity) because the number of calculations is not bounded, and we are dealing with continuous space (all points within the shapes).
Space Complexity
O(1)The brute force approach, as described, does not use any auxiliary data structures. It conceptually iterates through points of the circle and rectangle but doesn't explicitly store them. Therefore, the space used is constant, regardless of the size of the circle or rectangle, meaning the space complexity is O(1).

Optimal Solution

Approach

The most efficient way to check if a circle and rectangle overlap is to find the point on the rectangle closest to the circle's center. We can then determine overlap by comparing the distance between the closest point and the circle's center to the circle's radius.

Here's how the algorithm would work step-by-step:

  1. Find the coordinates of the center of the circle.
  2. Imagine the rectangle is just made of lines and corners. Find the point on the rectangle that is closest to the circle's center.
  3. Measure the distance between that closest point you found on the rectangle and the center of the circle.
  4. Compare that distance to the radius of the circle. If the distance is less than or equal to the radius, the circle and rectangle are overlapping.
  5. If the distance is greater than the radius, they aren't overlapping.

Code Implementation

def circle_rectangle_overlapping(
        rectangle_left_x,
        rectangle_top_y,
        rectangle_right_x,
        rectangle_bottom_y,
        circle_center_x,
        circle_center_y,
        circle_radius):

    closest_point_x = circle_center_x
    closest_point_y = circle_center_y

    # Determine the closest X coordinate on the rectangle to the circle's center.
    if circle_center_x < rectangle_left_x:
        closest_point_x = rectangle_left_x
    elif circle_center_x > rectangle_right_x:
        closest_point_x = rectangle_right_x

    # Determine the closest Y coordinate on the rectangle to the circle's center.
    if circle_center_y < rectangle_top_y:
        closest_point_y = rectangle_top_y
    elif circle_center_y > rectangle_bottom_y:
        closest_point_y = rectangle_bottom_y

    # Calculate the distance between the closest point and the circle's center.
    distance_between_closest_point_and_circle_center = (
        (closest_point_x - circle_center_x)**2 +
        (closest_point_y - circle_center_y)**2
    )**0.5

    # Check if the circle and rectangle overlap.
    if distance_between_closest_point_and_circle_center <= circle_radius:
        return True
    else:
        return False

Big(O) Analysis

Time Complexity
O(1)The provided solution involves finding the closest point on the rectangle to the circle's center, calculating the distance between these two points, and comparing it to the circle's radius. These operations involve a fixed number of arithmetic calculations and comparisons, regardless of the size or position of the rectangle or circle. Therefore, the time complexity is constant, or O(1).
Space Complexity
O(1)The algorithm calculates a closest point and a distance. It uses a few variables to store the circle's center coordinates, the closest point coordinates, and the calculated distance. The space required for these variables remains constant regardless of the size or position of the circle and rectangle. Therefore, the auxiliary space complexity is O(1).

Edge Cases

Circle radius is zero
How to Handle:
Return true if the circle center is inside the rectangle, otherwise return false.
Rectangle has zero width or height (is a line or point)
How to Handle:
Treat the rectangle as a line/point and check the distance from the circle center to the line/point.
Circle center is inside the rectangle
How to Handle:
Return true immediately as there is definite overlap.
Circle center is very far from the rectangle (potential overflow in distance calculations)
How to Handle:
Use double precision for distance calculations and check for potential overflow.
Rectangle coordinates are not properly ordered (x1 > x2 or y1 > y2)
How to Handle:
Ensure that rectangle coordinates are properly ordered before calculations.
Circle is extremely large, encompassing the entire rectangle.
How to Handle:
The general distance check method will correctly determine the overlap.
Coordinates and radius are negative
How to Handle:
Handle negative coordinates by translating them to a positive coordinate system if necessary for calculations, returning false if radius is negative.
Floating-point precision issues in distance calculations
How to Handle:
Use a small epsilon value for comparison when determining overlap due to floating-point inaccuracies.