题目难度: 中等
原题链接
今天继续更新程序员面试金典系列, 大家在公众号 算法精选 里回复 面试金典 就能看到该系列当前连载的所有文章了, 记得关注哦~
给定两个正方形及一个二维平面。请找出将这两个正方形分割成两半的一条直线。假设正方形顶边和底边与 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 轴平行的直线视为斜率无穷大)。
[-1,0]
和[2,0]
O(1)
: 只进行了几次常数时间的计算O(1)
: 只使用了几个常数空间的变量class Solution:
def cutSquares(self, square1: List[int], square2: List[int]) -> List[float]:
# 中心连线+三情况+斜截式求交点并排序
# 两个正方形的中心形成的直线即为所求
x1, y1, e1 = square1
x2, y2, e2 = square2
# 计算正方形的中心
xc1, yc1 = x1 + e1 / 2, y1 + e1 / 2
xc2, yc2 = x2 + e2 / 2, y2 + e2 / 2
if xc1 == xc2:
# 情况1: 对应直线平行于y轴, 所求交点就在最下面和最上面的两个边
return [xc1, min(y1, y2), xc1, max(y1 + e1, y2 + e2)]
if yc1 == yc2:
# 情况2: 对应直线平行于x轴, 所求交点就在最左面和最右面的两个边
return [min(x1, x2), yc1, max(x1 + e1, x2 + e2), yc2]
# 情况3: 对应直线不平行于坐标轴, 求出其斜率k和截距b
k = (yc2 - yc1) / (xc2 - xc1)
b = yc1 - k * xc1
def getJoints(square):
# 计算当前直线y=kx+b与正方形square的交点
x, y, e = square
res = []
for xx in (x, x + e):
# 先得到垂直边的交点
yy = k * xx + b
if y <= yy <= y + e:
# 注意计算出来的y值需要在边内部
res.append((xx, yy))
for yy in (y, y + e):
# 再得到水平边的交点
xx = (yy - b) / k
if x <= xx <= x + e:
# 注意计算出来的x值需要在边内部
res.append((xx, yy))
return res
# 求出直线与两个正方形的所有边的交点, 并排序
joints = getJoints(square1) + getJoints(square2)
joints.sort()
# 这样开头和结尾的两个点即为端点
return [joints[0][0], joints[0][1], joints[-1][0], joints[-1][1]]
大家可以在下面这些地方找到我~
我的 GitHub
我的 Leetcode
我的 CSDN
我的知乎专栏
我的头条号
我的牛客网博客
我的公众号: 算法精选, 欢迎大家扫码关注~