/**java
* 功能:在二維平面上,有一些點,請找出通過點數最多的那條線。[java] view plain copyapp
- /**
- * 思路:在任意兩點之間畫一條無線長的直線,用散列表追蹤那條直線出現的次數最多。時間複雜度O(N*N)
- * 注意:
- * 1)用斜率和y軸截距來肯定是不是同一條直線。
- * 2)浮點數不必定能用二進制數準確表示,所以檢查兩個浮點數的差值是否在某個極小值(epsilon)內。
- * 3)對於散列表而言,斜率相等,未必散列值相同。所以,將斜率減去一個極小值,並以獲得的結果flooredSlope做爲散列鍵。
- * 4)取得全部可能相等的直線,搜索三個位置:flooredSlope,flooredSlope-epsilon,flooredSlope+epsilon。
- * @param points
- * @return
- */
- public static MyLine1 findBestLine(GraphPoint[] points){
- MyLine1 bestLine=null;
- int bestCount=0;
-
- HashMap<Double,ArrayList<MyLine1>> lineBySlope=new HashMap<Double, ArrayList<MyLine1>>();
-
- for(int i=0;i<points.length-1;i++){
- for(int j=i+1;j<points.length;j++){
- MyLine1 line=new MyLine1(points[i],points[j]);
- insertLine(lineBySlope,line);
- int count=countEquivalentLines(lineBySlope,line);
- if(count>bestCount){
- bestCount=count;
- bestLine=line;
- }
- }
- }
- return bestLine;
-
- }
-
- private static int countEquivalentLines(HashMap<Double, ArrayList<MyLine1>> lineBySlope, MyLine1 line) {
- double key=line.floorToNearestEpsilon(line.slope);
- double eps=line.epsilon;
- int count=countEquivalentLines(lineBySlope.get(key), line)+countEquivalentLines(lineBySlope.get(key-eps), line)+
- countEquivalentLines(lineBySlope.get(key+eps), line);
-
- return count;
- }
-
- public static int countEquivalentLines(ArrayList<MyLine1> lines,MyLine1 line){
- if(lines==null)
- return 0;
- int count=0;
- for(MyLine1 paralleLine:lines){
- if(paralleLine==line)
- count++;
- }
- return count;
- }
-
- private static void insertLine(HashMap<Double, ArrayList<MyLine1>> lineBySlope, MyLine1 line) {
- ArrayList<MyLine1> lines=null;
- double key=line.floorToNearestEpsilon(line.slope);
- if(!lineBySlope.containsKey(key)){
- lines=new ArrayList<MyLine1>();
- lineBySlope.put(key, lines);
- }else{
- lines=lineBySlope.get(key);
- }
- lines.add(line);//注意此處添加的用法
- }
-
-
-
- class MyLine1{
- public static double epsilon=0.0001;
- public double slope,intercept;
- public boolean infiniteSlope=false;
-
- public MyLine1(GraphPoint p,GraphPoint q){
- if(Math.abs(p.x-q.x)>epsilon){//兩個點的x座標不一樣
- slope=(p.y-q.y)/(p.x-q.x);//斜率
- intercept=p.y-slope*p.x;//y軸截距
- }else{
- infiniteSlope=true;
- intercept=p.x;//x軸截距
- }
- }
-
- public double floorToNearestEpsilon(double d){
- int r=(int) (d/epsilon);//使原d保留小數位後的4位(epsilon=0.0001)
- return ((double)r)*epsilon;
- }
-
- public boolean isEquivalent(MyLine1 line){
- if((slope==line.slope)&&(intercept==line.intercept)&&(infiniteSlope==line.infiniteSlope))
- return true;
- return false;
- }
-
- public boolean isEquivalent(double a,double b){
- return Math.abs(a-b)<epsilon;
- }
-
-
-
- }
-
- class GraphPoint{
- int x;
- int y;
-
- public GraphPoint(int x,int y){
- this.x=x;
- this.y=y;
- }
- }