1401. 圆和矩形是否有重叠

164 阅读1分钟

题目:
给你一个以 (radius, xCenter, yCenter) 表示的圆和一个与坐标轴平行的矩形 (x1, y1, x2, y2) ,其中 (x1, y1) 是矩形左下角的坐标,而 (x2, y2) 是右上角的坐标。

如果圆和矩形有重叠的部分,请你返回 true ,否则返回 false 。

换句话说,请你检测是否 存在 点 (xi, yi) ,它既在圆上也在矩形上(两者都包括点落在边界上的情况)。

算法:
方法一:数学
不失一般性,先考虑如何判断圆(xr, yr)和矩形内的点(x, y)是否相交:
如果圆心到(x,y)的距离,小于等于半径,则点在圆内。
(xrx)2+(yry)2=dist<=r2(x_r-x)^2+(y_r-y)^2=dist <= r^2
如果矩形内有点(x,y)满足这个公式,则矩形和圆相交,否则不相交。

观察这个式子,(xrx_r, yry_r)和r是固定的,要满足这个公式,则要x,y到xrx_r, yry_r的距离分别都最小。(x, y可以沿坐标轴四个方向移动,x,y之间没有相关性,换而言之,x变大,y可以变大变小)

分类讨论,先考虑x

  1. x < x1时
    |xrx_r - x| 的最小值为x1 - xrx_r
  2. x1 <= x <= x2时 |xrx_r - x| 的最小值为0,此时圆和矩形相交
  3. x2 < x时
    |xrx_r - x| 的最小值为xrx_r - x2

对y也同理。

思路:先考虑一般性,得到一个公式,再观察公式如何取值,能满足条件。

func checkOverlap(radius int, xCenter int, yCenter int, x1 int, y1 int, x2 int, y2 int) bool {
    xMin := 0
    if xCenter < x1 ||  x2 < xCenter {
        xMin = min(abs(x1 - xCenter), abs(xCenter - x2))
    } 

    yMin := 0
    if yCenter < y1 || y2 < yCenter {
        yMin = min(abs(y1 - yCenter), abs(yCenter - y2))
    } 
    // fmt.Println(xMin, yMin, xCenter, yCenter)
    return xMin * xMin + yMin * yMin <= radius * radius
}

func min(a, b int) int {
    if a < b {
        return a
    }
    return b
}

func abs(a int) int {
    if a < 0 {
        return -a
    }
    return a
}