Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Break down a hard problem into reliable checkpoints, edge-case handling, and complexity trade-offs.
You are given two positive integers xCorner and yCorner, and a 2D array circles, where circles[i] = [xi, yi, ri] denotes a circle with center at (xi, yi) and radius ri.
There is a rectangle in the coordinate plane with its bottom left corner at the origin and top right corner at the coordinate (xCorner, yCorner). You need to check whether there is a path from the bottom left corner to the top right corner such that the entire path lies inside the rectangle, does not touch or lie inside any circle, and touches the rectangle only at the two corners.
Return true if such a path exists, and false otherwise.
Example 1:
Input: xCorner = 3, yCorner = 4, circles = [[2,1,1]]
Output: true
Explanation:
The black curve shows a possible path between (0, 0) and (3, 4).
Example 2:
Input: xCorner = 3, yCorner = 3, circles = [[1,1,2]]
Output: false
Explanation:
No path exists from (0, 0) to (3, 3).
Example 3:
Input: xCorner = 3, yCorner = 3, circles = [[2,1,1],[1,2,1]]
Output: false
Explanation:
No path exists from (0, 0) to (3, 3).
Example 4:
Input: xCorner = 4, yCorner = 4, circles = [[5,5,1]]
Output: true
Explanation:
Constraints:
3 <= xCorner, yCorner <= 1091 <= circles.length <= 1000circles[i].length == 31 <= xi, yi, ri <= 109Problem summary: You are given two positive integers xCorner and yCorner, and a 2D array circles, where circles[i] = [xi, yi, ri] denotes a circle with center at (xi, yi) and radius ri. There is a rectangle in the coordinate plane with its bottom left corner at the origin and top right corner at the coordinate (xCorner, yCorner). You need to check whether there is a path from the bottom left corner to the top right corner such that the entire path lies inside the rectangle, does not touch or lie inside any circle, and touches the rectangle only at the two corners. Return true if such a path exists, and false otherwise.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array · Math · Union-Find
3 4 [[2,1,1]]
3 3 [[1,1,2]]
3 3 [[2,1,1],[1,2,1]]
queries-on-number-of-points-inside-a-circle)check-if-point-is-reachable)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #3235: Check if the Rectangle Corner Is Reachable
class Solution {
private int[][] circles;
private int xCorner, yCorner;
private boolean[] vis;
public boolean canReachCorner(int xCorner, int yCorner, int[][] circles) {
int n = circles.length;
this.circles = circles;
this.xCorner = xCorner;
this.yCorner = yCorner;
vis = new boolean[n];
for (int i = 0; i < n; ++i) {
var c = circles[i];
int x = c[0], y = c[1], r = c[2];
if (inCircle(0, 0, x, y, r) || inCircle(xCorner, yCorner, x, y, r)) {
return false;
}
if (!vis[i] && crossLeftTop(x, y, r) && dfs(i)) {
return false;
}
}
return true;
}
private boolean inCircle(long x, long y, long cx, long cy, long r) {
return (x - cx) * (x - cx) + (y - cy) * (y - cy) <= r * r;
}
private boolean crossLeftTop(long cx, long cy, long r) {
boolean a = Math.abs(cx) <= r && (cy >= 0 && cy <= yCorner);
boolean b = Math.abs(cy - yCorner) <= r && (cx >= 0 && cx <= xCorner);
return a || b;
}
private boolean crossRightBottom(long cx, long cy, long r) {
boolean a = Math.abs(cx - xCorner) <= r && (cy >= 0 && cy <= yCorner);
boolean b = Math.abs(cy) <= r && (cx >= 0 && cx <= xCorner);
return a || b;
}
private boolean dfs(int i) {
var c = circles[i];
long x1 = c[0], y1 = c[1], r1 = c[2];
if (crossRightBottom(x1, y1, r1)) {
return true;
}
vis[i] = true;
for (int j = 0; j < circles.length; ++j) {
var c2 = circles[j];
long x2 = c2[0], y2 = c2[1], r2 = c2[2];
if (vis[j]) {
continue;
}
if ((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) > (r1 + r2) * (r1 + r2)) {
continue;
}
if (x1 * r2 + x2 * r1 < (r1 + r2) * xCorner && y1 * r2 + y2 * r1 < (r1 + r2) * yCorner
&& dfs(j)) {
return true;
}
}
return false;
}
}
// Accepted solution for LeetCode #3235: Check if the Rectangle Corner Is Reachable
func canReachCorner(xCorner int, yCorner int, circles [][]int) bool {
inCircle := func(x, y, cx, cy, r int) bool {
dx, dy := x-cx, y-cy
return dx*dx+dy*dy <= r*r
}
crossLeftTop := func(cx, cy, r int) bool {
a := abs(cx) <= r && cy >= 0 && cy <= yCorner
b := abs(cy-yCorner) <= r && cx >= 0 && cx <= xCorner
return a || b
}
crossRightBottom := func(cx, cy, r int) bool {
a := abs(cx-xCorner) <= r && cy >= 0 && cy <= yCorner
b := abs(cy) <= r && cx >= 0 && cx <= xCorner
return a || b
}
vis := make([]bool, len(circles))
var dfs func(int) bool
dfs = func(i int) bool {
c := circles[i]
x1, y1, r1 := c[0], c[1], c[2]
if crossRightBottom(x1, y1, r1) {
return true
}
vis[i] = true
for j, c2 := range circles {
if vis[j] {
continue
}
x2, y2, r2 := c2[0], c2[1], c2[2]
if (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2) > (r1+r2)*(r1+r2) {
continue
}
if x1*r2+x2*r1 < (r1+r2)*xCorner && y1*r2+y2*r1 < (r1+r2)*yCorner && dfs(j) {
return true
}
}
return false
}
for i, c := range circles {
x, y, r := c[0], c[1], c[2]
if inCircle(0, 0, x, y, r) || inCircle(xCorner, yCorner, x, y, r) {
return false
}
if !vis[i] && crossLeftTop(x, y, r) && dfs(i) {
return false
}
}
return true
}
func abs(x int) int {
if x < 0 {
return -x
}
return x
}
# Accepted solution for LeetCode #3235: Check if the Rectangle Corner Is Reachable
class Solution:
def canReachCorner(
self, xCorner: int, yCorner: int, circles: List[List[int]]
) -> bool:
def in_circle(x: int, y: int, cx: int, cy: int, r: int) -> int:
return (x - cx) ** 2 + (y - cy) ** 2 <= r**2
def cross_left_top(cx: int, cy: int, r: int) -> bool:
a = abs(cx) <= r and 0 <= cy <= yCorner
b = abs(cy - yCorner) <= r and 0 <= cx <= xCorner
return a or b
def cross_right_bottom(cx: int, cy: int, r: int) -> bool:
a = abs(cx - xCorner) <= r and 0 <= cy <= yCorner
b = abs(cy) <= r and 0 <= cx <= xCorner
return a or b
def dfs(i: int) -> bool:
x1, y1, r1 = circles[i]
if cross_right_bottom(x1, y1, r1):
return True
vis[i] = True
for j, (x2, y2, r2) in enumerate(circles):
if vis[j] or not ((x1 - x2) ** 2 + (y1 - y2) ** 2 <= (r1 + r2) ** 2):
continue
if (
(x1 * r2 + x2 * r1 < (r1 + r2) * xCorner)
and (y1 * r2 + y2 * r1 < (r1 + r2) * yCorner)
and dfs(j)
):
return True
return False
vis = [False] * len(circles)
for i, (x, y, r) in enumerate(circles):
if in_circle(0, 0, x, y, r) or in_circle(xCorner, yCorner, x, y, r):
return False
if (not vis[i]) and cross_left_top(x, y, r) and dfs(i):
return False
return True
// Accepted solution for LeetCode #3235: Check if the Rectangle Corner Is Reachable
impl Solution {
pub fn can_reach_corner(x_corner: i32, y_corner: i32, circles: Vec<Vec<i32>>) -> bool {
let n = circles.len();
let mut vis = vec![false; n];
let in_circle = |x: i64, y: i64, cx: i64, cy: i64, r: i64| -> bool {
(x - cx) * (x - cx) + (y - cy) * (y - cy) <= r * r
};
let cross_left_top = |cx: i64, cy: i64, r: i64| -> bool {
let a = cx.abs() <= r && (cy >= 0 && cy <= y_corner as i64);
let b = (cy - y_corner as i64).abs() <= r && (cx >= 0 && cx <= x_corner as i64);
a || b
};
let cross_right_bottom = |cx: i64, cy: i64, r: i64| -> bool {
let a = (cx - x_corner as i64).abs() <= r && (cy >= 0 && cy <= y_corner as i64);
let b = cy.abs() <= r && (cx >= 0 && cx <= x_corner as i64);
a || b
};
fn dfs(
circles: &Vec<Vec<i32>>,
vis: &mut Vec<bool>,
i: usize,
x_corner: i32,
y_corner: i32,
cross_right_bottom: &dyn Fn(i64, i64, i64) -> bool,
) -> bool {
let c = &circles[i];
let (x1, y1, r1) = (c[0] as i64, c[1] as i64, c[2] as i64);
if cross_right_bottom(x1, y1, r1) {
return true;
}
vis[i] = true;
for j in 0..circles.len() {
if vis[j] {
continue;
}
let c2 = &circles[j];
let (x2, y2, r2) = (c2[0] as i64, c2[1] as i64, c2[2] as i64);
if (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) > (r1 + r2) * (r1 + r2) {
continue;
}
if x1 * r2 + x2 * r1 < (r1 + r2) * x_corner as i64
&& y1 * r2 + y2 * r1 < (r1 + r2) * y_corner as i64
&& dfs(circles, vis, j, x_corner, y_corner, cross_right_bottom)
{
return true;
}
}
false
}
for i in 0..n {
let c = &circles[i];
let (x, y, r) = (c[0] as i64, c[1] as i64, c[2] as i64);
if in_circle(0, 0, x, y, r) || in_circle(x_corner as i64, y_corner as i64, x, y, r) {
return false;
}
if !vis[i]
&& cross_left_top(x, y, r)
&& dfs(
&circles,
&mut vis,
i,
x_corner,
y_corner,
&cross_right_bottom,
)
{
return false;
}
}
true
}
}
// Accepted solution for LeetCode #3235: Check if the Rectangle Corner Is Reachable
function canReachCorner(xCorner: number, yCorner: number, circles: number[][]): boolean {
const inCircle = (x: bigint, y: bigint, cx: bigint, cy: bigint, r: bigint): boolean => {
const dx = x - cx;
const dy = y - cy;
return dx * dx + dy * dy <= r * r;
};
const crossLeftTop = (cx: bigint, cy: bigint, r: bigint): boolean => {
const a = BigInt(Math.abs(Number(cx))) <= r && cy >= 0n && cy <= BigInt(yCorner);
const b =
BigInt(Math.abs(Number(cy - BigInt(yCorner)))) <= r &&
cx >= 0n &&
cx <= BigInt(xCorner);
return a || b;
};
const crossRightBottom = (cx: bigint, cy: bigint, r: bigint): boolean => {
const a =
BigInt(Math.abs(Number(cx - BigInt(xCorner)))) <= r &&
cy >= 0n &&
cy <= BigInt(yCorner);
const b = BigInt(Math.abs(Number(cy))) <= r && cx >= 0n && cx <= BigInt(xCorner);
return a || b;
};
const n = circles.length;
const vis: boolean[] = new Array(n).fill(false);
const dfs = (i: number): boolean => {
const [x1, y1, r1] = circles[i].map(BigInt);
if (crossRightBottom(x1, y1, r1)) {
return true;
}
vis[i] = true;
for (let j = 0; j < n; j++) {
if (vis[j]) continue;
const [x2, y2, r2] = circles[j].map(BigInt);
if ((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) > (r1 + r2) * (r1 + r2)) {
continue;
}
if (
x1 * r2 + x2 * r1 < (r1 + r2) * BigInt(xCorner) &&
y1 * r2 + y2 * r1 < (r1 + r2) * BigInt(yCorner) &&
dfs(j)
) {
return true;
}
}
return false;
};
for (let i = 0; i < n; i++) {
const [x, y, r] = circles[i].map(BigInt);
if (inCircle(0n, 0n, x, y, r) || inCircle(BigInt(xCorner), BigInt(yCorner), x, y, r)) {
return false;
}
if (!vis[i] && crossLeftTop(x, y, r) && dfs(i)) {
return false;
}
}
return true;
}
Use this to step through a reusable interview workflow for this problem.
Track components with a list or adjacency matrix. Each union operation may need to update all n elements’ component labels, giving O(n) per union. For n union operations total: O(n²). Find is O(1) with direct lookup, but union dominates.
With path compression and union by rank, each find/union operation takes O(α(n)) amortized time, where α is the inverse Ackermann function — effectively constant. Space is O(n) for the parent and rank arrays. For m operations on n elements: O(m × α(n)) total.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Wrong move: Temporary multiplications exceed integer bounds.
Usually fails on: Large inputs wrap around unexpectedly.
Fix: Use wider types, modular arithmetic, or rearranged operations.