Skip to content

Commit ebde85a

Browse files
committed
Solved LeetCode 1401 using closest-point clamping with squared-distance check to test circle-rectangle overlap in O(1) time with runtime = 0ms.
1 parent d87abaa commit ebde85a

1 file changed

Lines changed: 194 additions & 0 deletions

File tree

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
package LeetCode.Maths;
2+
3+
public class LeetCode_1401_CircleAndRectangleOverlapping {
4+
public static void main(String[] args) {
5+
6+
// Sample 1 (LeetCode): circle inside rectangle -> true
7+
System.out.println("Sample 1 (inside) -> CaseByCase: "
8+
+ checkOverlapCaseByCase(1, 0, 0, -1, -1, 1, 1)
9+
+ " | ClosestPoint: " + checkOverlap(1, 0, 0, -1, -1, 1, 1)
10+
+ " (expected: true)");
11+
12+
// Sample 2 (LeetCode): circle far away -> false
13+
System.out.println("Sample 2 (far) -> CaseByCase: "
14+
+ checkOverlapCaseByCase(1, 1, 1, 1, -3, 2, -1)
15+
+ " | ClosestPoint: " + checkOverlap(1, 1, 1, 1, -3, 2, -1)
16+
+ " (expected: false)");
17+
18+
// Sample 3 (LeetCode): circle intersects an edge -> true
19+
System.out.println("Sample 3 (edge) -> CaseByCase: "
20+
+ checkOverlapCaseByCase(1, 0, 0, -1, 0, 0, 1)
21+
+ " | ClosestPoint: " + checkOverlap(1, 0, 0, -1, 0, 0, 1)
22+
+ " (expected: true)");
23+
24+
// Edge case: circle touches a corner exactly (distance == radius)
25+
System.out.println("Edge (corner touch) -> CaseByCase: "
26+
+ checkOverlapCaseByCase(5, 0, 0, 3, 4, 10, 10)
27+
+ " | ClosestPoint: " + checkOverlap(5, 0, 0, 3, 4, 10, 10)
28+
+ " (expected: true)");
29+
30+
// Edge case: circle just outside a corner (distance > radius)
31+
System.out.println("Edge (just outside corner) -> CaseByCase: "
32+
+ checkOverlapCaseByCase(4, 0, 0, 3, 4, 10, 10)
33+
+ " | ClosestPoint: " + checkOverlap(4, 0, 0, 3, 4, 10, 10)
34+
+ " (expected: false)");
35+
36+
// Edge case: zero radius circle inside rectangle -> true
37+
System.out.println("Edge (zero radius inside) -> CaseByCase: "
38+
+ checkOverlapCaseByCase(0, 0, 0, -1, -1, 1, 1)
39+
+ " | ClosestPoint: " + checkOverlap(0, 0, 0, -1, -1, 1, 1)
40+
+ " (expected: true)");
41+
42+
// Edge case: huge coordinates to exercise long arithmetic
43+
System.out.println("Edge (large coords) -> CaseByCase: "
44+
+ checkOverlapCaseByCase(100000, 0, 0, -1000000, -1000000, 1000000, 1000000)
45+
+ " | ClosestPoint: " + checkOverlap(100000, 0, 0, -1000000, -1000000, 1000000, 1000000)
46+
+ " (expected: true)");
47+
}
48+
49+
50+
/*
51+
Approach 1: Exhaustive case analysis
52+
53+
Enumerate every spatial relationship between the circle's center and
54+
the rectangle:
55+
1. Center inside the rectangle.
56+
2. Center directly above / below (aligned in x, y outside).
57+
3. Center directly left / right (aligned in y, x outside).
58+
4. Center outside a corner region — check the distance from center
59+
to each of the 4 corners.
60+
61+
If any of these conditions hold, the circle overlaps the rectangle.
62+
63+
This approach is verbose but very explicit about the geometry.
64+
It's easy to get wrong (missing cases, using <= vs < incorrectly).
65+
66+
Time: O(1)
67+
Space: O(1)
68+
*/
69+
static boolean checkOverlapCaseByCase(
70+
int radius, int xCenter, int yCenter,
71+
int x1, int y1, int x2, int y2) {
72+
73+
// Center is inside the rectangle
74+
if (x1 <= xCenter && xCenter <= x2 && y1 <= yCenter && yCenter <= y2) {
75+
return true;
76+
}
77+
78+
// Center is directly above the rectangle (x aligned, y above top edge)
79+
if (x1 <= xCenter && xCenter <= x2 && y2 <= yCenter && yCenter <= y2 + radius) {
80+
return true;
81+
}
82+
83+
// Center is directly below the rectangle (x aligned, y below bottom edge)
84+
if (x1 <= xCenter && xCenter <= x2 && y1 - radius <= yCenter && yCenter <= y1) {
85+
return true;
86+
}
87+
88+
// Center is directly to the left of the rectangle (y aligned, x left of left edge)
89+
if (x1 - radius <= xCenter && xCenter <= x1 && y1 <= yCenter && yCenter <= y2) {
90+
return true;
91+
}
92+
93+
// Center is directly to the right of the rectangle (y aligned, x right of right edge)
94+
if (x2 <= xCenter && xCenter <= x2 + radius && y1 <= yCenter && yCenter <= y2) {
95+
return true;
96+
}
97+
98+
// Center is outside a corner region — check squared distance to each corner
99+
if (distanceSq(xCenter, yCenter, x1, y2) <= (long) radius * radius) return true; // upper-left
100+
if (distanceSq(xCenter, yCenter, x1, y1) <= (long) radius * radius) return true; // lower-left
101+
if (distanceSq(xCenter, yCenter, x2, y2) <= (long) radius * radius) return true; // upper-right
102+
if (distanceSq(xCenter, yCenter, x2, y1) <= (long) radius * radius) return true; // lower-right
103+
104+
return false;
105+
}
106+
107+
/*
108+
Squared Euclidean distance between (ux, uy) and (vx, vy).
109+
110+
Uses long arithmetic to avoid overflow when coordinates are large
111+
(LeetCode allows coordinates up to +/- 10^9, and squares reach 10^18).
112+
*/
113+
static long distanceSq(int ux, int uy, int vx, int vy) {
114+
long dx = (long) ux - vx;
115+
long dy = (long) uy - vy;
116+
return dx * dx + dy * dy;
117+
}
118+
119+
120+
/*
121+
Approach 2: Closest point on rectangle + distance check (clean)
122+
123+
Key insight:
124+
The circle overlaps the rectangle iff the distance from the circle's
125+
center to the CLOSEST point on the rectangle is <= radius.
126+
127+
The closest point on an axis-aligned rectangle to a point (cx, cy) is
128+
obtained by clamping cx and cy to the rectangle's coordinate ranges:
129+
closestX = clamp(cx, x1, x2)
130+
closestY = clamp(cy, y1, y2)
131+
132+
Then compare squared distance against radius^2.
133+
134+
This single formula subsumes all the cases in Approach 1:
135+
- center inside: closest = center, distance = 0
136+
- center beside an edge: closest is on the edge, distance = perp gap
137+
- center outside a corner: closest is the corner
138+
139+
Time: O(1)
140+
Space: O(1)
141+
*/
142+
static boolean checkOverlap(
143+
int radius, int xCenter, int yCenter,
144+
int x1, int y1, int x2, int y2) {
145+
146+
// Clamp center coordinates to the rectangle's bounds
147+
int closestX = Math.max(x1, Math.min(xCenter, x2));
148+
int closestY = Math.max(y1, Math.min(yCenter, y2));
149+
150+
// Squared distance from circle center to closest point on rectangle
151+
long dx = (long) xCenter - closestX;
152+
long dy = (long) yCenter - closestY;
153+
154+
return dx * dx + dy * dy <= (long) radius * radius;
155+
}
156+
}
157+
158+
/*
159+
---------------------------------------------------------
160+
Complexity Analysis
161+
---------------------------------------------------------
162+
163+
Approach 1: Exhaustive case analysis
164+
165+
Time Complexity: O(1)
166+
167+
- A fixed number of coordinate comparisons and 4 distance checks.
168+
169+
Space Complexity: O(1)
170+
171+
- Only a few primitive variables.
172+
173+
Key Observation: The overlap condition decomposes into a handful of
174+
geometric cases (center inside, along an edge's projection, or near a corner).
175+
176+
177+
Approach 2: Closest point on rectangle + distance check
178+
179+
Time Complexity: O(1)
180+
181+
- Two clamp operations, a difference, and one squared-distance comparison.
182+
183+
Space Complexity: O(1)
184+
185+
- Only a few primitive variables.
186+
187+
Key Observation: Overlap ⟺ distance from circle center to the closest
188+
point on the rectangle ≤ radius. Clamping the center coordinates to the
189+
rectangle bounds gives that closest point directly, replacing 10 branches
190+
with a single unified formula. Use long arithmetic to avoid overflow on
191+
large coordinate values.
192+
193+
---------------------------------------------------------
194+
*/

0 commit comments

Comments
 (0)