数据结构之分治法(最短距离)-(十一)

28 篇文章 2 订阅
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));
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值