从一组给定的点中得到的矩形的数量

201 阅读4分钟

在这篇文章中,我们讨论了如何从一组给定的坐标点中找到可能的矩形(与轴平行)的数量

内容表

  1. 例子
  2. 蛮力方法
  3. 有效的方法
  4. 算法
  5. 实施
  6. 复杂度分析

例子

假设我们有一个坐标集**[{1,1}, {7,1}, {1,4}, {1,5}, {7,4}, {7,5}] 。**

8 | 
7 | 
6 |  (1,5)             (7,5)
5 | *                 *
4 | *                 *
3 |  (1,4)             (7,4)
2 |  (1,1)             (7,1)
1 | *                 *
0 | _  _  _  _  _  _  _  _
    1  2  3  4  5  6  7  8
   

   
So, three rectangles can be formed from the given points.
*   (1,4)----(7,4)
     |         | 
     |         |    
    (1,1)----(7,1) 

*   (1,5)----(7,5)
     |         |
     |         |    
    (1,1)----(7,1) 

*   (1,5)----(7,5)
     |         |
     |         |    
    (1,4)----(7,4)
    

蛮力方法

蛮力方法可以从给定的集合中逐一选择四个坐标点,并对每个四边形寻找是否可以形成一个矩形。
选择每个四边形将需要O(n^4)的时间。所以这不是解决这个问题的有效方法。

高效的方法

对于一个矩形来说,对角线的端点可以是(x1,y1)和(x2,y2),给定x1!=x2和y1!=y2。这是因为我们给定的是矩形应该与轴平行。另外,在我们得到两点作为对角线的端点后,记住矩形的属性,矩形的另外两个端点将是(x1,y2)和(x2,y1).这在下图中很明显。

(x1,y1)       (x2,y1) 
     *_ _ _ _*
     | \     |
     |  \    | 
     |   \   |
     |    \  |
     |     \ |
     |      \|
     *_ _ _ _*
(x1,y2)       (x2,y2)

因此,解决这个问题的基本方法是,对于每一对点,例如(x1,y1)和(x2,y2),我们认为它们是某个矩形的对角线端点,并检查初始集合中是否存在点(x1,y2)和(x2,y1),以便形成一个矩形。

算法

  • 初始化一个变量Answer来存储可能的矩形的数量。让它最初为0。
  • 现在我们从给定的集合中一次取两个点,并检查它们是否能形成矩形对角线的端点,即如果它们的形式是(x1, y1)和(x2, y2),其中x1!=x2,y1!=y2。
  • 现在我们检查这个集合是否包含点(x1,y2)和(x2,y1),以便形成一个矩形(矩形的另外两个顶点)。
  • 如果这两个点存在于这个集合中,那么就有可能形成一个矩形,因此我们增加答案变量。

让我们通过一个例子来理解这一点。
让我们假设我们的坐标集为**[{1,1}, {7,1}, {1,4}, {1,5}, {7,4}, {7,5}] 。**

步骤。

  • 答案=0

  • 取点(1,1)和(7,1)
    ,它们不是
    (
    x1,y1)和(x2,y2)的形式,因为y1=y2,
    所以它们不能构成对角线的端点。

  • 取点(1,1)和(1,4)
    ,它们不是
    (
    x1,y1)和(x2,y2)的形式,因为x1=x2,
    所以它们不能构成对角线的端点。

  • 取点(1,1)和(1,5)
    ,它们不是
    (
    x1,y1)和(x2,y2)的形式,因为x1=x2,所以它们不能构成对角
    线的端点

  • 以(1,1)和(7,4)
    为例,它们的形式是(x1,y1)和(x2,y2
    ),

    因此它们可以构成对角线的端点。
    现在检查所得矩形的另外两个顶点是否存在于集合中。
    另外两个顶点是(x1,y2)和(x2,y1)即(1,4)和(7,1),它们都存在于集合中,因此可以构成矩形。
    因此答案递增。
    答案=1

  • 类似地检查其他的配对,我们得到总共3个矩形的可能性。

实施。

#include <iostream>
#include<set>
using namespace std;
set<pair<int, int>> points;
int main() {
    int n;
    cin>>n;
    int a,b;
    for(int i=0;i<n;i++){
        cin>>a>>b;;
        points.insert(make_pair(a,b));
    }
    
    int answer = 0;
    
    for(auto i=points.begin(); i!=points.end(); i++)
    {
        for(auto j= i+1; j!=points.end(); j++)
        {
            pair<int, int> p1 = *i;
            pair<int, int> p2 = *j;

            if(p1.first == p2.first || p1.second == p2.second)
                continue;

            pair<int, int> p3 = make_pair(p1.first, p2.second);
            pair<int, int> p4 = make_pair(p2.first, p1.second);

            if(points.find(p3) != points.end() && points.find(p4) != points.end())
                ++answer;
             
        }
        
    }

    cout<<answer;

    return 0;
    
}

复杂度分析

考虑每一对对角线端点需要O(n^2)的时间。
而使用find函数检查矩形的另外两个端点是否存在于集合中需要O(log n)的时间。
所以总的时间复杂性是O(n^2 log n)

同时,我们不需要任何额外的空间来进行计算,所以空间复杂度是恒定的

因此,在OpenGenus的这篇文章结束时,你一定对如何从给定的坐标点集合中找到可能的矩形数量有了清晰的认识。