9.7数学与概率(四)——在二维平面上,有一些点,请找出经过点数最多的那条线

/**

* 功能:在二维平面上,有一些点,请找出经过点数最多的那条线。

/**
	 * 思路:在任意两点之间画一条无线长的直线,用散列表追踪那条直线出现的次数最多。时间复杂度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;
	}
}

*/

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-08 06:25:08

9.7数学与概率(四)——在二维平面上,有一些点,请找出经过点数最多的那条线的相关文章

在二维平面上,有一些点。请找出经过点数最多的那条线

Line findBestLine(GraphPoint[] points) { Line bestLine =null; int bestCount=0; HashMap<Double ,ArrayList<Line>> linesBySlope= new HashMap<Double,ArrayList<Line>>(); for(int i=0;i<points.length;i++) { for(int j=i+1;j<points.le

9.7数学与概率(三)——在二维平面上,有两个正方形,请找出一条直线,能够将这两个正方形对半分

/** * 功能:在二维平面上,有两个正方形,请找出一条直线,能够将这两个正方形对半分. * 假定正方形的上下两条边与x轴平行. */ /** * 考虑: * 线的准确含义,可能性有: * 1)由斜率和y轴截距确定: * 2)由这条边上的任意两点确定: * 3)线段,以正方形的边作为起点和终点. * * 假设:这条线的端点应该落在正方形的边上. * 思路:要将两个正方形对半分,这条线必须连接两个正方形的中心点. */ public class Square { //正方形的四条边 int lef

数字之魅:寻找二维平面上的最近的点对

在二维平面上的n个点中,如何快速的找出最近的一对点,就是最近点对问题. 初看这个题,可能感觉有点儿复杂. 方案一:蛮力法.数组中总共包含N个数,所以我们可以把平面内所有的点按X轴排序,然后依次算出后一个坐标与前面所有左边的距离,然后用Min和position来记录最近的距离和两个坐标.该方案和在一维空间求两个最近点的距离有点儿类似,其时间复杂度为:O(N*N). 方案二:在一维空间里,我们知道如果数组有序,我们可以很快找出最近的两个点.我们可以用O(N*logN)的时间复杂度来对数据进行排序[快

编写一个表示二维平面上的点的类MyPoint,满足以下条件: 1、定义private的成员变量x和y,表示点的x和y坐标,类型为double

编写一个表示二维平面上的点的类MyPoint,满足以下条件:1.定义private的成员变量x和y,表示点的x和y坐标,类型为double2.定义两个MyPoint的构造方法,一个构造方法不带参数,而且x和y的初始值为0,另一个构造方法有两个参数,参数名为x和y,类型为double,用这两个参数分别作为初始x和y坐标3.定义一个getD方法,有一个类型为MyPoint的对象参数,功能为返回当前对象和参数对象这两个坐标点的距离,返回值为double类型4.编写测试的main方法,调用getD计算两

剑指Offer(Java版)第六十五题:给定一棵二叉搜索树,请找出其中的第k小的结点。 例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4。

/*给定一棵二叉搜索树,请找出其中的第k小的结点.例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4.*//*二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值*///思路:从最左边的叶子节点开始找起. import java.util.*; public clas

二维平面上判断点是否在三角形内

最近在项目中碰到的这个问题,在此记录一下.已知三角形的三个顶点坐标,判断某个点是否在三角形中(在三角形的边上,我们也视作在三角形中),本文给出了三种方法.   算法1 利用面积法,如上图所示,如果点P在三角形ABC的内部,则三个小三角形PAB, PBC, PAC的面积之和 = ABC的面积,反之则不相等. 已知三角形的三个顶点坐标求其面积,可以根据向量的叉乘,参考here. 该算法详见后面的函数:IsPointInTriangle1   算法2 首先看一下这个问题,如何判断某两个点在某条直线的同

给定一颗二叉搜索树,请找出其中的第k大的结点。例如, 5 / \ 3 7 /\ /\ 2 4 6 8 中,按结点数值大小顺序第三个结点的值为4。

/* struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) { } }; */ class Solution { public: TreeNode* KthNode(TreeNode* pRoot, int k) { //中序递归     int count = 0;              if(co

二维平面上判断点在三角形内的最优算法

园子里有很多关于点是否在三角形内的文章,提供了各种方法.这让人很纠结,到底该用哪种算法?这里提供一套我认为最优的算法.如果你有不同的意见,亦或有更好的算法,欢迎来讨论. 算法使用的是同向法,其原理是:假设点P位于三角形ABC内,会有这样一个规律:三角形的每一个边,其对角点与P在边的同一侧:或者说三角形的每一个顶点与P在其对角边的同一侧. (1)代码 // 2D vector class Vec2 { public: Vec2() { x = 0.0f; y = 0.0f; } Vec2(floa

POJ 3241 Object Clustering 二维平面曼哈顿距离最小生成树

题目链接:点击打开链接 题意: 给定二维平面上的n个点坐标,常数k 下面n行给出坐标 求一个最小生成树,问第k大的边是多少. 任意两个点间建一条边的花费是其曼哈顿距离. 思路:转自:点击打开链接 一.曼哈顿距离最小生成树 曼哈顿距离最小生成树问题可以简述如下: 给定二维平面上的N个点,在两点之间连边的代价为其曼哈顿距离,求使所有点连通的最小代价. 朴素的算法可以用O(N2)的Prim,或者处理出所有边做Kruskal,但在这里总边数有O(N2)条,所以Kruskal的复杂度变成了O(N2logN