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