package com.lip.datastructure;
/**
* @author lip
* 分治法,所谓分治当然是分而治之,化整为零。
* 分治法分为两部分,1.分(Divide)2.治(Conquer)
* 在排序算法中我们用到的二分排序就是分治法最经典的一个例子
* 传统的分治法要运行两次及其以上的递归算法,一般用分治法解决问题的时间复杂度是O(N*lgN)
*/
public class DivideAndConquer
{
/*求平面上两个点的最短距离
* 方法一:就是两个for循环求得任意两点间的距离,然后去取得最小值,毫无疑问时间复杂度O(N^2)(N*(N-1)/2)
* 方法二:就是分治法。
* 思路:假设平面上点已经按照x和y的大小顺序排序分布在平面上,有一条y=k的线把平面分为两部分,那么最短距离d存在这三种可能。
* 1.k线的左侧,最小值dleft
* 2.k线的右侧,最小值dright
* 3.一个点p1在k线的左侧,一个点p2在k线的右侧,并且(p1.x-p2.x)<min{dleft,dright}
* (如果大于那最小值就在最左侧或者右侧了,那么最小值取min{dleft,dright})
*/
public static void main(String[] args)
{
Point p1=new Point(1, 1);
Point p2=new Point(2, 5);
Point p3=new Point(2, 2);
Point p4=new Point(4, 6);
Point p5=new Point(5, 8);
Point p6=new Point(6, 6);
Point p7=new Point(4, 2);
Point p8=new Point(5, 2);
Point p9=new Point(7, 4);
Point[]points={p1,p2,p3,p4,p5,p6,p7,p8,p9};
System.out.println(getMinDistance(points, 0, 8));
}
/**
* @param start
* @param end
* @return start,end范围内两个相聚最近的点
*/
public static double getMinDistance(Point []points,int start,int end)
{
//如果只有1个或者两个元素,那么直接计算距离
if(start==end)
return Integer.MAX_VALUE;
else if(start+1==end)
return points[start].toPoint(points[end]);
int mid=(end+start)/2;
double minLeft=getMinDistance(points, start, mid);
double minRight=getMinDistance(points, mid+1, end);
double len=minLeft<minRight?minLeft:minRight;
double minCenter=Integer.MAX_VALUE;
for(int i=start;i<=mid;i++)
{
if(points[mid].getX()-points[i].getX()>len)
break;
for(int j=mid+1;j<=end;j++)
{
if(points[j].getX()-points[mid].getX()>len)
break;
double temp=points[i].toPoint(points[j]);
if(minCenter>temp)
minCenter=temp;
}
}
return getMin(minCenter, minLeft, minRight);
}
//得到三个值中的最小值
public static double getMin(double a,double b,double c)
{
if(a<=b&&a<=c)
return a;
else if(b<=a&&b<=c)
return b;
else if(c<=a&&c<=b)
return c;
return -1;
}
}
class Point
{
private int x;
private int y;
public int getX()
{
return x;
}
public void setX(int x)
{
this.x = x;
}
public int getY()
{
return y;
}
public void setY(int y)
{
this.y = y;
}
public Point(int x,int y)
{
this.x=x;
this.y=y;
}
/**
* @param p
* @return 返回到一个点的距离
*/
public double toPoint(Point p)
{
return Math.sqrt((p.x-this.x)*(p.x-this.x)+(p.y-this.y)*(p.y-this.y));
}
}