[CC150] Find a line passing the most number of points

Problem: Given a two-dimensional graph with points on it, find a line which passes the most number of points.

此题是Cracking the code 5th edition 第七章第六题,思路就是 n choose 2, 所以时间复杂度是O(n^2),因为没有更快的办法。

此题的难点在于两点一线计算出的斜率是浮点型,不好比较equality。所以其中需要有一个精确到哪一位的概念,英文是 round to a given place value.

我认为此题书中给的解法特别傻逼,而且时间复杂度也超出了O(n^2),故自己写了一个更好的版本。

另,关于使用自定义类用作HashMap的键值,如何重写equals()和hashCode(),下面的代码给出的很好的示范。

package chapter7;



import java.util.HashMap;



// given a two-dimensional graph with points on it,

// find a line which passes the most number of points

// Time: O(N^2), N is number of points



// The tricky part is checking the equality of slope

// which is of type double.

// My solution is floor all values to an epsilon value

// which specifies the desired precision



public class P6 {

	

	public Line findBestLine(GraphPoint[] points){

		Line bestLine = null;

		int bestCount = 0;

		HashMap<Line, Integer> lineCounts = 

				new HashMap<Line, Integer>();

		

		for(int i = 0; i < points.length; ++i){

			for(int j = i+1; j < points.length; ++j){

				Line line = new Line(points[i], points[j]);

				int currentCount;

				

				if(lineCounts.containsKey(line)){

					currentCount = lineCounts.get(line) + 1;

				}else{

					currentCount = 1;

				}

				lineCounts.put(line, currentCount);

				

				if(currentCount > bestCount){

					bestCount = currentCount;

					bestLine = line;

				}

			}

		}

		

		return bestLine;

	}

}





class Line{

	// for precision 

	// slope and intercept values are floored to epsilon

	public static double epsilon = .0001;

	

	// properties for a normal line

	public double slope;

	public double y_intercept;

	

	// properties for a verticle line

	public boolean infinite_slope = false;

	public double x_intercept;

	

	public Line(GraphPoint p1, GraphPoint p2){

		

		if(p1.x == p2.x){

			this.infinite_slope = true;

			this.x_intercept = p1.x;

			

		}else{

			this.slope = (p1.y - p2.y) / (p1.x - p2.x);

			this.y_intercept = p1.y - slope * p1.x;

		

		}

		

		// floor all properties

		this.slope = floor(this.slope);

		this.x_intercept = floor(this.x_intercept);

		this.y_intercept = floor(this.y_intercept);

	}



	public double floor(double val){

		int val2 = (int)(val / epsilon);

		return val2 * epsilon;

	}

	

	@Override

	public int hashCode(){

		if(infinite_slope){

			return (int) x_intercept;

		}else{

			return (int) (slope + y_intercept);

		}

	}

	

	@Override

	public boolean equals(Object obj){

		if(this == obj)

			return true;

		if(obj == null)

			return false;

		if(getClass() != obj.getClass())

			return false;

		

		Line other = (Line)obj;

		

		if(infinite_slope && other.infinite_slope){ // both true

			return x_intercept == other.x_intercept;

			

		}else if(infinite_slope || other.infinite_slope){ // one true, one false

			return false;

		}

		else{ // both false

			return slope == other.slope && y_intercept == other.y_intercept;

		}

	}

}





class GraphPoint{

	// assume that x and y are both floored

	// to some point

	public double x;

	public double y;

}

  

你可能感兴趣的:(number)