【问题标题】:Finding repeated points in 2D plane在二维平面中查找重复点
【发布时间】:2017-09-06 20:59:23
【问题描述】:

我试图从给定的 10 个点中找到重复的点,其中每个点都有 x 和 y 值。我已经编写了以下代码,但无法获得正确的结果。输出应该是 {3,5},{4,2},{2,4},{7,8}

  #include <iostream>
#include<stdlib.h>
using namespace std;

struct point
{
int x;
int y;
};
void distinctPoints(point arr[], int size)
{
cout<<"Repeated Points"<<endl;
    cout<<"x, y"<<endl;
  for(int i = 0; i< size; i++)
    for(int j = i+1; j< size; j++)
        {
        if ((arr[i].x==arr[j].x) && (arr[i].y==arr[j].y))
            {
            cout<<arr[j].x <<", "<<arr[j].y<<endl;
            break;
            }
        }
}
int main()
{   int size=10;
    point points[size]={{3,5},{4,2},{2,4},{3,5},{7,8},{7,8},{4,2},{7,8},{3,5},{2,4}};
    distinctPoints(points, size);
    return 0;
}

【问题讨论】:

  • 您的算法复杂度为 n^2,加上您多次打印相同的点...一个建议是先对您的点列表进行排序,然后检查是否有连续重复。
  • 将您的代码放入编译器,无需进行任何更改。工作得非常好,除了当然点被多次写出。

标签: c++ arrays struct


【解决方案1】:

您的方法(一旦纠正,正如VHS 的回答所做的那样)对于少量点可能没问题,但是对于更大的数据集,O(N2)算法可能效率太低。

您可以利用在 std::unordered_set 中插入元素所花费的平均成本时间,即使您需要为您的类编写比较函数和哈希函数。

下面介绍的算法使用两个 unordered_set:

  • uniques 最终存储了源容器中存在的所有元素,没有重复。
  • repeated 仅存储多次出现的元素的唯一实例。

仅当元素已存在于uniques 中但不在repeated 中时,它才会复制到输出。

#include <iostream>
#include <vector>
#include <unordered_set>
#include <algorithm>
#include <iterator>

struct point
{
    int x, y;

    bool operator== (point const& b) const
    {
        return x == b.x  &&  y == b.y;
    }
};

namespace std {

template<> struct hash<point>
{
    std::size_t operator() (point const& p) const
    {
        return (std::hash<int>{}(p.x) << 1) ^ std::hash<int>{}(p.y);
    }
};

}

std::ostream& operator<< (std::ostream& os, point const& pt)
{
    return os << '(' << pt.x << ", " << pt.y << ')';
}

template<class InputIt, class OutputIt>
OutputIt copy_repeated_values(InputIt first, InputIt last, OutputIt dest)
{
    using value_type = typename InputIt::value_type;

    std::unordered_set<value_type> uniques, repeated;

    return std::copy_if(
        first, last, dest, [&] (value_type const& value) {
            return
                not uniques.insert(value).second  &&
                repeated.insert(value).second;
        }
    );
}

int main()
{
    std::vector<point> points {
        {3,5}, {4,2}, {2,4}, {3,5}, {7,8}, {7,8}, {4,2}, {7,8}, {3,5}, {2,4}
    };

    copy_repeated_values(
        std::begin(points), std::end(points), 
        std::ostream_iterator<point>(std::cout, " ")
    );

    std::cout << '\n';
}

输出是:

(3, 5) (7, 8) (4, 2) (2, 4)

【讨论】:

    【解决方案2】:

    我已经调整了您的 distinctPoints 方法,这样即使重复出现两次以上,它也不会多次打印重复。请参阅以下编辑:

    void distinctPoints(point arr[], int size)
    {
      point dups[size];
      cout<<"Distinct Points"<<endl;
      cout<<"x, y"<<endl;
      for(int i = 0; i < size; i++)
        for(int j = 0; j < size; j++) {
            if ((arr[i].x==arr[j].x) && (arr[i].y==arr[j].y)) {
                if(j < i) {
                    break;
                }
                else if( j == i) {
                    continue;
                }
                else {
                    cout<<arr[i].x <<", "<<arr[i].y<<endl;
                    break;
                }
            }
        }
    
    }
    

    【讨论】:

      【解决方案3】:

      这应该可以实现您想要实现的目标,我正在使用 c++ 中的 set 和 maps 来处理唯一条目。

      地图会跟踪已经访问过的点。

      #include <iostream>
      #include<stdlib.h>
      #include <set>
      #include <map>
      using namespace std;
      
      struct point
      {
      int x;
      int y;
      };
      
      map<pair<int, int>, int> mapCountOfPoints;
      
      set<pair<int, int> > disPoints;
      
      void distinctPoints(point arr[], int size)
      {
        for(int i=0; i<size; i++) {
          pair<int, int> temp = make_pair(arr[i].x, arr[i].y);
          if(mapCountOfPoints.find(temp) != mapCountOfPoints.end()) {
            disPoints.insert(temp);
          } else {
            mapCountOfPoints[temp] = 1;
          }
        }         
      
        // Now we will iterate over the set to get the distinct set of points
        for(set<pair<int, int>>::iterator it=disPoints.begin(); it!=disPoints.end(); it++) {
          cout<<it->first<<" "<<it->second<<endl;
        }
      
      }
      int main()
      {   int size=10;
          point points[size]={{3,5},{4,2},{2,4},{3,5},{7,8},{7,8},{4,2},{7,8},{3,5},{2,4}};
          distinctPoints(points, size);
          return 0;
      }
      

      希望这会有所帮助!

      【讨论】:

      • 哦,我的坏@PicaudVincent 让我修复它
      • 更新了我的答案,这应该可以解决它
      • 由于您还改进了代码的样式,我可以建议将函数重命名为指示发生什么操作的名称吗?并且你摆脱了全局变量?
      • @Aziuth 你觉得哪个方法名好,我在想 findDistinctPointsAndPrint()
      • @zenwraight 这是描述性的,但有点长。此外,必须将它们合二为一表明它们应该分开,恕我直言。我只是选择 printDistinctPoints (顺便说一句,“不同”?不是“重复”?)。但我真正要做的不是让它打印任何东西,而是使用函数vector&lt;Point&gt; findDistinctPoints(const vector&lt;Point&gt;&amp; input) 和函数void print(const vector&lt;Point&gt;&amp; input),调用类似 print(findDistinctPoints(points));` 的函数。功能清晰,创建清晰可重复使用的打印功能。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-22
      • 1970-01-01
      • 2017-04-12
      • 2021-06-09
      相关资源
      最近更新 更多