1. 题目
1.1 题意
给定圆和矩形,判断两个图形是否有重叠部分
1.2 分析
两个图形重叠有两种情况,相交和包含。
先考虑相交:相交的话圆至少和矩形的某条边有交点,因为矩形四条边都平行/重合于坐标轴,所以可以求圆形和矩形的四条直线中满足情况的交点,但是矩形四条线段不是直线,交点需要判断。
简单推导一下:
(
x
−
x
0
)
2
+
(
y
−
y
0
)
2
=
R
2
,
(
(
x
0
,
y
0
)
为圆心
)
与直线
x
=
x
A
的交点:
(x-x_0)^2+(y-y_0)^2=R^2,((x_0,y_0)为圆心)与直线x=x_A的交点:
(x−x0)2+(y−y0)2=R2,((x0,y0)为圆心)与直线x=xA的交点:
(
y
A
−
y
0
)
2
=
R
2
−
(
x
−
x
0
)
2
(y_A-y_0)^2=R^2-(x-x_0)^2
(yA−y0)2=R2−(x−x0)2
y
A
−
y
0
=
±
R
2
−
(
x
−
x
0
)
2
y_A-y_0=\pm\sqrt{R^2-(x-x_0)^2}
yA−y0=±R2−(x−x0)2
y
A
=
y
0
±
R
2
−
(
x
−
x
0
)
2
y_A=y_0\pm\sqrt{R^2-(x-x_0)^2}
yA=y0±R2−(x−x0)2
注意点细节:首先能否开根号,其次这个解出的
y
A
y_A
yA是否在矩形的范围内
接着考虑包含:因为已经排除了相交的情况,所以此时圆和矩形不相交。有两种情况。
情况1:矩形包含圆形,此时圆心在矩形内
情况2:圆形包含矩形,此时矩形的顶点到圆心距离小于半径(或者垂直于x轴的直径的两个端点包含了矩形的y轴的范围)
1 <= radius <= 2000
-1e4 <= xCenter, yCenter <= 1e4
-1e4 <= x1 < x2 <= 1e4
-1e4 <= y1 < y2 <= 1e4
1.3 我的解法
class Solution {
public:
double fun1(int x, int y, int r, int z){
return y + sqrt(r * r - (z - x) * (z - x) );
}
double fun2(int x, int y, int r, int z){
return y - sqrt(r * r - (z - x) * (z - x) );
}
bool checkOverlap(int radius, int xCenter, int yCenter, int x1, int y1, int x2, int y2) {
if(radius * radius >= (x1 - xCenter) * (x1-xCenter) ){
// 判断是否可以开根号
double ya = fun1(xCenter, yCenter, radius, x1);
double yb = fun2(xCenter, yCenter, radius, x1);
if(ya >= y1 && ya <=y2){
// 判断范围是否在矩形的边上
return true;
}
if(yb >= y1 && yb <=y2){
return true;
}
}
if(radius * radius >= (x2 - xCenter) * (x2-xCenter) ){
double ya = fun1(xCenter, yCenter, radius, x2);
double yb = fun2(xCenter, yCenter, radius, x2);
if(ya >= y1 && ya <=y2){
return true;
}
if(yb >= y1 && yb <=y2){
return true;
}
}
if(radius * radius >= (y1 - yCenter) * (y1-yCenter) ){
double xa = fun1(yCenter, xCenter, radius, y1);
double xb = fun2(yCenter, xCenter, radius, y1);
if(xa >= x1 && xa <=x2){
return true;
}
if(xb >= x1 && xb <=x2){
return true;
}
}
if(radius * radius >= (y2 - yCenter) * (y2-yCenter) ){
double xa = fun1(yCenter, xCenter, radius, y2);
double xb = fun2(yCenter, xCenter, radius, y2);
if(xa >= x1 && xa <=x2){
return true;
}
if(xb >= x1 && xb <=x2){
return true;
}
}
if(xCenter>=x1 && xCenter<=x2 && yCenter>=y1 && yCenter<=y2){
// 正方形包含圆
// 圆心在矩形内
return true;
}
if((x1 - xCenter) * (x1 - xCenter) + (y1 - yCenter) * (y1 - yCenter) <= radius * radius){
// 圆包含正方形
// 矩形的顶点到圆心距离小于半径
return true;
}
return false;
}
};
1.4 学习题解反思
时间复杂度O(1), 空间复杂度O(1)
因为矩形的摆放位置很特殊,所以题解中找圆心到矩形区域的最小距离,优雅。
1.5 bug日记
1.5.1 包含情况
开始就被样例的case误导,先入为主,没想到包含的情况
2. 后记
仅分享自己的想法,有意见和指点非常感谢