题目链接
平分正方形
题目描述
注意点
- square.length == 3
- square[2] > 0
- 若同时有多条直线满足要求,则选择斜率最大的一条计算并返回(与Y轴平行的直线视为斜率无穷大)
解答思路
- 平分正方形的直线是两个正方形中间点相连的直线,需要特殊考虑的是:中间点相连与y轴平行(中间点的x相同),此时x1, x2就是x,y1, y2就是中心线与两个正方形最上方、最下方的边的交点;中间点相连与x轴平行(中间点的y相同),此时y1, y2就是y,x1, x2就是中心线与两个正方形最左方、最右方的边的交点
- 对于一般情况,中心线的方程是y = kx + b,其可能与两个正方形的最上方、最下方、最左方、最右方相交,规律是:如果Math.abs(k)大于1,中心线会偏向于y轴,其会与最上方、最下方的边相交;如果如果Math.abs(k)小于1,中心线会偏向x轴,其会与最左方、最右方的边相交
- 对于k大于0和小于0的情况会导致中心线与正方向相应边相交的点的x1、x2、y1、y2的大小关系不同,所以最终如果x1 > x2,还需要将x1与x2进行交换,y1与y2进行交换
代码
class Solution {
public double[] cutSquares(int[] square1, int[] square2) {
int edge1 = square1[2];
int edge2 = square2[2];
// 两个正方形的中心点
double midX1 = square1[0] + edge1 / 2.0;
double midY1 = square1[1] + edge1 / 2.0;
double midX2 = square2[0] + edge2 / 2.0;
double midY2 = square2[1] + edge2 / 2.0;
double left = Math.min(square1[0], square2[0]);
double right = Math.max(square1[0] + edge1, square2[0] + edge2);
double bottom = Math.min(square1[1], square2[1]);
double top = Math.max(square1[1] + edge1, square2[1] + edge2);;
double[] res = new double[4];
if (midX1 == midX2) {
// 中点相连与y轴平行
res[0] = midX1;
res[2] = midX1;
res[1] = bottom;
res[3] = top;
} else if (midY1 == midY2) {
// 中点相连与x轴平行
res[0] = left;
res[2] = right;
res[1] = midY1;
res[3] = midY1;
} else {
// y = kx + b;
double k = (midY2 - midY1) / (midX2 - midX1);
double b = midY1 - k * midX1;
if (Math.abs(k) > 1) {
// 斜率大于1与上下相交
res[0] = (bottom - b) / k;
res[2] = (top - b) / k;
res[1] = bottom;
res[3] = top;
} else {
// 斜率小于1与左右相交
res[0] = left;
res[2] = right;
res[1] = k * left + b;
res[3] = k * right + b;
}
}
// 保证x1 < x2
if (res[0] > res[2]) {
swap(res, 0, 2);
swap(res, 1, 3);
}
return res;
}
public void swap(double[] res, int i, int j) {
double tmp = res[i];
res[i] = res[j];
res[j] = tmp;
}
}
关键点
- 怎么找到平分正方形的中间线
- 注意考虑中心线与x轴平行、与y轴平行的特殊情况
- 最终结果需要保证x1 < x2,如果x1 = x2,需要保证y1 < y2