2014-04-14 44 views
1

假設您在2D平面上有點陣列。點定義如下:如何查找位於同一條直線上的最大點數

class Point { 
    public int x; 
    public int y; 

    Point(int _x, int _y) { x = _x; y = _y; } 
} 

我怎麼能找到在java中同一直線上的最大點數?

+0

不可能在不到解決比O(N^2) –

+0

@ user3530447,我們談論的一組這裏的任意點?任何所需的時間複雜性如果你拿兩分,這兩點總是出現在同一條線上,那麼下一步就是看看這條線上的其他點是否「撒謊」。你爲所有的點對做這個。這很慢(我認爲它的O(n^2)) –

+0

點在2D平面上。 – user3530447

回答

0
/** 
* Definition for a point. 
* struct Point { 
*  int x; 
*  int y; 
*  Point() : x(0), y(0) {} 
*  Point(int a, int b) : x(a), y(b) {} 
* }; 
*/ 
class Solution { 
public: 
    int maxPoints(vector<Point> &points) { 
     int n = points.size(); //number of the points 
     if (n<=2){return n;} 
     vector<double> k; //vector to store the slops for one point with all the other points 
     int res = 0; 

     for (int i=0;i<n;i++){ // for each point in the 2d plane 
      k.clear(); 
      int dup = 1; // number of the duplicates with currrent point 
      for (int j=0;j<n;j++){ 
       if (i!=j){ // for every other point 
        if (points[i].x-points[j].x==0){ // if the slope is a vertical line 
         if (points[i].y-points[j].y==0){ // if the point j is the same as point i 
          dup++; 
         }else{ 
          k.push_back(99999); //store the vertical line to a specific slope 
         } 
        }else{ // if it is the regular slop between point i and j 
         k.push_back(10000*(points[i].y-points[j].y)/(points[i].x-points[j].x)); // store the slope 
        } 
       } 
      } 

      sort(k.begin(),k.end()); //sort the slopes for counting 

      int pp = 1; //number of points in the same line of the point i 
      if (k.size()==0){pp=0;} 

      for (int jj=1;jj<k.size();jj++){ //count pp 
       if (k[jj]==k[jj-1]){ 
        pp++; 
       }else{ 
        if (pp+dup>res){res=pp+dup;} // res = pp + the number of duplicates 
        pp = 1; 
       } 
      } 
      if (pp+dup>res){res = pp+dup;} 
     } 

     return res; 
    } 
}; 
3

對於數組中的每個點,計算此點與其他點之間的角度。使用hashMap計算具有相同角度的人數。預計時間爲O(n^2)

僞代碼

int result = 0; 
for(int i = 0; i < data.length; i++){ 
    HashMap<Double, Integer> map = new HashMap(); 
    for(int j = 0; j < data.length; j++){ 
     if(i == j) 
      continue; 
     double angle = calculateAngle(data[i], data[j]); 
     if(map.containsKey(slope)){ 
      map.put(angle, map.get(slope) + 1); 
     }else{ 
      map.put(angle, 1); 
     } 
     result = max(result, map.get(slope)); 
    } 
} 

注:如NiklasB的評論提到,採用雙會導致一些問題的精度,尤其是當我們需要比較這些浮點值。我們可以通過使用NiklasB建議的Rational類來避免這種情況。 (或者不那麼精確,使用this

+1

Ahm這肯定會失敗,因爲浮點數不準確。你將不得不存儲一些歸一化的整數分數。此外,您還需要處理兩個以上點具有相同x座標的情況。在這種情況下,斜率是無窮大的。 –

+1

平行線如何?也會失敗 –

+1

@TejasPatel平行線?這是從一個點作爲起點到其他點的斜率,而不是Ox或Oy軸:) –

3

下面是使用精確的算法在Java中的解決方案:

import java.util.List; 
import java.util.Map; 
import java.util.HashMap; 

public class Solver { 
    public int maxPointsOnLine(List<Point> points) { 
     int ans = 0; 
     Map<Line, Integer> lines = new HashMap<Line, Integer>(); 
     for (Point a : points) { 
      int max = 0; 
      int same = 0; 
      lines.clear(); 

      for (Point b : points) { 
       if (a.x == b.x && a.y == b.y) { 
        ++same; 
       } else { 
        Line line = new Line(b.x - a.x, b.y - a.y); 
        Integer count = lines.get(line); 
        if (count == null) { 
         count = 0; 
        } 
        ++count; 
        lines.put(line, count); 
        max = Math.max(max, count); 
       } 
      } 
      ans = Math.max(ans, same + max); 
     } 
     return ans; 
    } 

    static class Line { 
     final int dx; 
     final int dy; 

     Line(int dx, int dy) { 
      if (dy == 0) { 
       dx = Math.abs(dx); 
      } 
      else if (dy < 0) { 
       dx = -dx; 
       dy = -dy; 
      } 
      int gcd = gcd(Math.abs(dx), dy); 
      dx /= gcd; 
      dy /= gcd; 
      this.dx = dx; 
      this.dy = dy; 
     } 

     @Override 
     public boolean equals(Object other) { 
      if (!(other instanceof Line)) { 
       return false; 
      } 
      Line another = (Line)other; 
      return dx == another.dy && dy == another.dy; 
     } 

     @Override 
     public int hashCode() { 
      return 31 * dx + dy; 
     } 
    } 

    static int gcd(int a, int b) { 
     return b == 0 ? a : gcd(b, a % b); 
    } 
} 
+1

當然這適用於垂直線?順便說一句,你可以通過使用Pham –

+0

提出的算法來擺脫Line類。我確信它不適用於垂直線。 :)我已經編輯了我的答案,以使用一般形式的直線方程。 – dened

+0

我已經改寫了我的解決方案,使其更加緊湊。 – dened

相關問題