Count Number of Triples in an array that are collinear

后端 未结 6 932
梦谈多话
梦谈多话 2021-02-01 09:31

I was asked this Interview Question (C++,algos)and had no idea how to solve it.

Given an array say Arr[N] containing Cartesian coordinates of N distinct points count the

6条回答
  •  你的背包
    2021-02-01 09:55

    It's trivial to see that you can get all the pairs of points and their slope & y-intercepts in O(n^2) time. So the output is:

    IndexB Slope Y-Intercept IndexA

    Of course, we won't insert any entries where IndexA = IndexB.

    Let's have this table indexed on (IndexB,Slope,Y), which forces our insert into this table as O(log(n))

    After we fill out this table with new records (B',S',Y',A'), we check to see if we already have an element such that B'=A of the existing table and B!=A' of the new record (meaning we have a unique triplet) that matches the slope and Y-intercept (meaning collinear). If this is the case and A < B < B', increment the count by 1.

    EDIT: One clarifying remark. We need to make sure that we fill this table "backwards" first, taking all the pairs that wouldn't satisfy A < B (< C). This ensures that they will exist in the table before we start testing for their existence.

    EDIT: Wow my C++ is rusty... took a while.

    #include 
    #include 
    #include 
    #include 
    #include 
    
    using namespace std;
    
    #define ADD_POINT(xparam,yparam) { point x; x.x = xparam; x.y = yparam; points.push_back(x); };
    
    #define EPSILON .001
    
    class line {
    public:
      double slope;
      double y;
      int a;
      int b;
    
      bool operator< (const line &other) const{
        if(this->a < other.a)
          return true;
        else if(this->a==other.a){
          if(this->slope-other.slope < -EPSILON)
            return true;
          else if(fabs(this->slope-other.slope) < EPSILON){
            if(this->y-other.y < -EPSILON)
              return true;
            else
              return false;
          }else
            return false;
        }else
          return false;
      }
    
      line(double slope, double y, int a, int b){
        this->slope = slope;
        this->y = y;
        this->a = a;
        this->b = b;
      }
    
      line(const line &other){
        this->slope = other.slope;
        this->y = other.y;
        this->a = other.a;
        this->b = other.b;
      }
    };
    
    class point {
    public:
      double x;
      double y;
    };
    
    int main(){
      vector points;
      ADD_POINT(0,0);
      ADD_POINT(7,28);
      ADD_POINT(1,1);
      ADD_POINT(2,3);
      ADD_POINT(2,4);
      ADD_POINT(3,5);
      ADD_POINT(3,14);
      ADD_POINT(5,21);
      ADD_POINT(9,35);
    
      multiset lines;
      for(unsigned int x=0;x::const_iterator p = lines.begin(); p != lines.end(); ++p){
        //cout << "Line: " << p->a << " " << p->b << " " << p->slope << " " << p->y << endl;
        line theline = *p;
        line conj(theline.slope,theline.y,theline.b,-1);
        multiset::iterator it;
        pair::iterator,multiset::iterator> ret;
        ret = lines.equal_range(conj);
        for(it = ret.first; it!=ret.second; ++it){
          //cout << "  Find: " << it->a << " " << it->b << " " << it->slope << " " << it->y << endl;
          int a = theline.a;
          int b = theline.b;
          int c = it->b;
          if(a < b && b < c){
            cout << a << " " << b << " " << c << std::endl;
          }
        }
      }
    
    
      //cout << points[0].x << std::endl;
    
    }
    

提交回复
热议问题