[LeetCode 双周赛23] 3. 圆和矩形是否有重叠(暴力、数学、向量、顶级解法)

文章目录

    • 1. 题目来源
    • 2. 题目说明
    • 3. 题目解析
      • 方法一:暴力+常规解法
      • 方法二:数学+巧妙解法
      • 方法三:数学+向量+坐标变换+顶级解法

1. 题目来源

链接:5361. 圆和矩形是否有重叠

2. 题目说明

[LeetCode 双周赛23] 3. 圆和矩形是否有重叠(暴力、数学、向量、顶级解法)_第1张图片
[LeetCode 双周赛23] 3. 圆和矩形是否有重叠(暴力、数学、向量、顶级解法)_第2张图片

3. 题目解析

方法一:暴力+常规解法

这题被我直接忽略掉了,我对不起我的专业…

遍历矩形的所有点,与圆心位置进行判断,若任意两点距离小于等于半径就返回 true 就行了,否则返回 false 就行了。

暴力法就是这么的无脑,我一开始以为这是一个平面上的无穷多点,而非有限的整数点,所以首先就排除了暴力法,画图画有思路但一直卡样例,真是无语了,真是对不起我的专业。但是暴力法也是很多缺陷,若数据量一大,一定 TLE 了。

参见代码如下:

// 执行用时 :124 ms, 在所有 C++ 提交中击败了100.00%的用户
// 内存消耗 :6 MB, 在所有 C++ 提交中击败了100.00%的用户

class Solution {
public:
    bool checkOverlap(int r, int x, int y, int x1, int y1, int x2, int y2) {
        for (int i = x1; i <= x2; ++i) {
            for (int j = y1; j <= y2; ++j) {
                if ((x - i) * (x - i) + (y - j) * (y - j) <= r * r) return true;
            }
        }
        return false;
    }
};

方法二:数学+巧妙解法

很简单的一道计算几何的问题。借用一下题解区大佬的图片。
[LeetCode 双周赛23] 3. 圆和矩形是否有重叠(暴力、数学、向量、顶级解法)_第3张图片
就分别判段这三种情况就行了。很巧妙的解法。在这里要注意,C++ 多个数字用 min 函数进行求 min 时,需要加上大括号,否则产生歧义。

class Solution {
public:
    bool checkOverlap(int r, int x, int y, int x1, int y1, int x2, int y2) {
        // 圆心在矩形内部
        if (x >= x1 and x <= x2 and y >= y1 and y <= y2) return true;
        //圆在正方形的 左 右 上 下 时的相交条件
        if ((y >= y1 and y <= y2 and x < x1 and x1 - x <= r) or 
            (y >= y1 and y <= y2 and x > x2 and x - x2 <= r) or 
            (x >= x1 and x <= x2 and y > y2 and y - y2 <= r) or 
            (x >= x1 and (x <= x2 and y < y1 and y1 - y <= r))) return true;
        return min({(x1 - x) * (x1 - x) + (y2 - y) * (y2 - y), (x2 - x) * (x2 - x) + (y2 - y) * (y2 - y), 
                   (x2 - x) * (x2 - x) + (y1 - y) * (y1 - y), (x1 - x) * (x1 - x) + (y1 - y) * (y1 - y)}) <= r * r;
    }
};

方法三:数学+向量+坐标变换+顶级解法

也是在题解区学到的解法,来自知乎大佬 Milo Yip 在知乎的分享。

大佬在知乎讲解的很清楚了,不再过多阐述。若有疑惑可留言交流。这个方法具有很强的拓展性。

参见代码如下:

// 执行用时 :0 ms, 在所有 C++ 提交中击败了100.00%的用户
// 内存消耗 :6 MB, 在所有 C++ 提交中击败了100.00%的用户

class Solution {
public:
    bool checkOverlap(int radius, int x_center, int y_center, int x1, int y1, int x2, int y2) {
        // (tx,ty)表示未变换之前的矩形中心
        int tx = (x1 + x2) / 2, ty = (y1 + y2) / 2; 
        // (tdx,tdy)表示变换之后的矩形中心
        int tdx = -tx, tdy = -ty; 
        // (x11,y11),(x21,y21)表示矩形的左下和右上端点
        int x11 = x1 + tdx, x21 = x2 + tdx, y11 = y1 + tdy, y21 = y2 + tdy;
        // (xc,yc)表示变换到第一象限的圆心坐标 
        int xc = abs(x_center + tdx), yc = abs(y_center + tdy); 
        // (ux,uy)表示u向量
        int ux = xc - x21, uy = yc - y21;
        // 将u向量中的x,y小于0的置为0
        ux = max(0, ux), uy = max(0, uy);
        // 判断
        return ux * ux + uy * uy <= radius * radius;  
    }
};

你可能感兴趣的:(LeetCode周赛)