Title description
[Leetcode] 5361. Whether circle and rectangle overlap (Circle and Rectangle Overlapping)
Give you a circle represented by (radius, x_center, y_center) and a rectangle parallel to the coordinate axis (x1, y1, x2, y2), where (x1, y1) are the coordinates of the lower left corner of the rectangle, (x2, y2) Are the coordinates of the upper right corner.
If the circle and rectangle overlap, please return True, otherwise return False.
In other words, please check whether there is a point (xi, yi), which is both on the circle and the rectangle (both include the case where the point falls on the boundary).
Example 1:
Input: radius = 1, x_center = 0, y_center = 0, x1 = 1, y1 = -1, x2 = 3, y2 = 1
Output: true
Explanation: Circle and rectangle have a common point (1,0)
Example 2:
Input: radius = 1, x_center = 0, y_center = 0, x1 = -1, y1 = 0, x2 = 0, y2 = 1
Output: true
Example 3:
Input: radius = 1, x_center = 1, y_center = 1, x1 = -3, y1 = -3, x2 = 3, y2 = 3
Output: true
Example 4:
Input: radius = 1, x_center = 1, y_center = 1, x1 = 1, y1 = -3, x2 = 2, y2 = -1
Output: false
prompt:
- 1 <= radius <= 2000
- -10^4 <= x_center, y_center, x1, y1, x2, y2 <= 10^4
- x1 < x2
- y1 < y2
First answer
Ideas
Because the coordinates are plastic, it can be violent. Traverse each pixel in the square area to determine whether it is within the circle.
Code:
class Solution {
public:
bool checkOverlap(int radius, int x_center, int y_center, int x1, int y1, int x2, int y2) {
long r2 = radius*radius;
for(int y=y1; y<=y2; y++){
for(int x=x1; x<=x2; x++){
int dx = x-x_center;
int dy = y-y_center;
long d = dx*dx + dy*dy;
if(d <= r2)
return true;
}
}
return false;
}
};
result:
Second answer
Ideas I
saw a more general method, which should be able to be used when most rectangular areas intersect.
Regional division method. The space is divided into 9 regions, and the circle adopts different strategies in different regions. For details, please refer to here. The
divided areas are as shown in the figure below: The
intersection of circles and rectangles can be classified into the following three types:
Code:
// 思路:
// 数学思路不是每一题都适用,因此这里尝试一下看似普适的区域划分方法
class Solution {
public:
bool checkOverlap(int radius, int x_center, int y_center, int x1, int y1, int x2, int y2) {
// 圆心在矩形内情况
if(x1 <= x_center && x_center <= x2 && y1 <= y_center && y_center <= y2)
return true;
// 圆心在矩形上下左右区域
// 上
if(x1 <= x_center && x_center <= x2 && y_center >= y2 && y_center-y2 <= radius)
return true;
// 下
if(x1 <= x_center && x_center <= x2 && y_center <= y1 && y1 - y_center <= radius)
return true;
// 左
if(y1 <= y_center && y_center <= y2 && x_center <= x1 && x1-x_center <= radius)
return true;
// 右
if(y1 <= y_center && y_center <= y2 && x_center >= x2 && x_center-x2 <= radius)
return true;
// 圆心在矩形斜对角线上
long r2 = radius*radius;
if(abs(x1-x_center)*abs(x1-x_center) + abs(y2-y_center)*abs(y2-y_center) <= r2)
return true;
if(abs(x1-x_center)*abs(x1-x_center) + abs(y1-y_center)*abs(y1-y_center) <= r2)
return true;
if(abs(x2-x_center)*abs(x2-x_center) + abs(y1-y_center)*abs(y1-y_center) <= r2)
return true;
if(abs(x2-x_center)*abs(x2-x_center) + abs(y2-y_center)*abs(y2-y_center) <= r2)
return true;
return false;
}
};
result:
Third answer
Idea The
first wifiii
solution in China in the Weekly Competition .
This solution can be understood from the perspective of the area division method.
The intersection of a circle and a rectangle can be classified into the following three situations. In the figure, Figure 1 can be used to determine whether the center of the circle is within the rectangle, and Figure 2 can be used to determine whether the four corners of the rectangle are within the circle, but Figure 3 is more troublesome, and there is no corresponding point to bring in to determine the intersection wifiii
. The algorithm concisely realizes the judgment of the third case.
Three kinds:
Code:
// 思路:
// 周赛冠军的解法,用区域划分来理解的话,它的方法是简洁的实现了当圆心在矩形外的上下左右区域的相交判断
class Solution {
public:
bool checkOverlap(int radius, int x_center, int y_center, int x1, int y1, int x2, int y2) {
auto incircle = [&](int x, int y){
return (x-x_center)*(x-x_center) + (y-y_center)*(y-y_center) <= radius*radius;};
auto insqure = [&](int x, int y){
return x1 <= x && x <= x2 && y1 <= y && y <= y2;};
// 这里组合有9个坐标,其中圆心和四个角点,这五个坐标可以判断图1和图2的相交情况。
// 剩下4个坐标用于判断图3那种相交情况
vector<int> vx{
x_center, x1, x2}, vy{
y_center, y1, y2};
bool is_ok = false;
for(auto & xx : vx)
for(auto & yy : vy)
if(incircle(xx, yy) && insqure(xx, yy))
is_ok = true;
return is_ok;
}
};
result:
Fourth answer
Idea
Mathematical method. Refer to know the method here .
Note that this method is the best in theory, but decimals are generated in the actual process, so there is a certain error. The process is as follows:
first map the center of the circle to the first quadrant:
then judge the size of the vector u and the size of the radius to get the intersection:
Code:
// 思路:
// 用[知乎这里提到的方法](https://www.zhihu.com/question/24251545/answer/27184960)
class Solution {
public:
bool checkOverlap(int radius, int x_center, int y_center, int x1, int y1, int x2, int y2) {
// 向量cp转到第一象限
double cpx = abs(x_center-(x1+x2)/2.0);
double cpy = abs(y_center-(y1+y2)/2.0);
double hx = x2 - (x1+x2)/2.0;
double hy = y2 - (y1+y2)/2.0;
double ux = max(cpx-hx, 0.0);
double uy = max(cpy-hy, 0.0);
return ux*ux + uy*uy <= radius*radius;
}
};
result: