程序员面试金典 - 面试题 16.13. 平分正方形(数学)

1. 题目

给定两个正方形及一个二维平面。请找出将这两个正方形分割成两半的一条直线。
假设正方形顶边和底边与 x 轴平行。

每个正方形的数据square包含3个数值,正方形的左下顶点坐标[X,Y] = [square[0],square[1]],以及正方形的边长square[2]。
所求直线穿过两个正方形会形成4个交点,请返回4个交点形成线段的两端点坐标(两个端点即为4个交点中距离最远的2个点,这2个点所连成的线段一定会穿过另外2个交点)。
2个端点坐标[X1,Y1]和[X2,Y2]的返回格式为{X1,Y1,X2,Y2},要求若X1 != X2,需保证X1 < X2,否则需保证Y1 <= Y2。

若同时有多条直线满足要求,则选择斜率最大的一条计算并返回(与Y轴平行的直线视为斜率无穷大)。

示例:
输入:
square1 = {-1, -1, 2}
square2 = {0, -1, 2}
输出: {-1,0,2,0}
解释: 直线 y = 0 能将两个正方形同时分为等面积的两部分,返回的两线段端点为[-1,0][2,0]

提示:
square.length == 3
square[2] > 0

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/bisect-squares-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2. 解题

  • 过两个正方形中心的直线
  • 分成斜率无穷大(垂直于x轴)、斜率绝对值>=1、< 1 考虑
  • 交点在上下边,还是在左右边
class Solution {
public:
    vector<double> cutSquares(vector<int>& square1, vector<int>& square2) {
    	if(square1[1] > square2[1])
    		swap(square1,square2);//第一个的左下角y坐标更小
    	double cx1, cy1, cx2, cy2, r1, r2;
    	r1 = square1[2]/2.0;
    	r2 = square2[2]/2.0;
    	cx1 = square1[0]+r1;//中心坐标
    	cy1 = square1[1]+r1;
    	cx2 = square2[0]+r2;
    	cy2 = square2[1]+r2;
    	if(cx1==cx2)//斜率无穷大
    		return {cx1,cy1-r1,cx1,max(cy1+r1,cy2+r2)};
    	else//斜率存在,分两种情况,与上下边相交,左右边相交
    	{
    		double k = (cy1-cy2)/(cx1-cx2);
    		double b = cy1-k*cx1;
            vector<vector<double>> points;
    		if(abs(k)>=1)//交点在上下边
    		{
    			points.push_back({(cy1+r1-b)/k, cy1+r1});
                points.push_back({(cy1-r1-b)/k, cy1-r1});
                points.push_back({(cy2+r2-b)/k, cy2+r2});
                points.push_back({(cy2-r2-b)/k, cy2-r2});
                sort(points.begin(),points.end());
                return {points.front()[0],points.front()[1],points.back()[0],points.back()[1]};
    		}
    		else//交点在左右边
    		{
    			points.push_back({cx1+r1, k*(cx1+r1)+b});
                points.push_back({cx1-r1, k*(cx1-r1)+b});
                points.push_back({cx2+r2, k*(cx2+r2)+b});
                points.push_back({cx2-r2, k*(cx2-r2)+b});
                sort(points.begin(),points.end());
                return {points.front()[0],points.front()[1],points.back()[0],points.back()[1]};
    		}
    	}
    }
};

4 ms 8.6 MB

你可能感兴趣的:(《程序员面试金典》)