最近点对(Java实现)


最近点对问题:

在二维平面上的n个点中,快速的最近的一对点的距离。

java实现:

package p2;

import static java.lang.Math.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Scanner;

public class CloestPair {
	// 坐标点
	static class Point {
		public Point() {
		}

		public Point(double x, double y) {
			this.x = x;
			this.y = y;
		}
		double x;
		double y;
	}

	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		while (true) {
			int n = scanner.nextInt();
			Point[] ps = new Point[n];
			for (int i = 0; i < n; i++) {
				double x = scanner.nextDouble();
				double y = scanner.nextDouble();
				ps[i] = new Point(x, y);
			}
			// 按照X轴坐标升序排序
			Arrays.sort(ps, new Comparator<Point>() {
				@Override
				public int compare(Point o1, Point o2) {
					if (o1.x < o2.x)
						return -1;
					if (o1.x > o2.x)
						return 1;
					if (o1.y < o2.y)
						return -1;
					if (o1.y > o2.y)
						return 1;
					return 0;
				}
			});
			double minDis = minDistance(ps, 0, n - 1);
			System.out.println(minDis);
		}

	}

	/**
	 * 点对之间的最小距离
	 * 
	 * @param ps
	 * @param l
	 * @param r
	 * @return
	 */
	public static double minDistance(Point[] ps, int l, int r) {
		/**
		 * 同一个点,不存在点对,距离不能取0,返回最大值
		 */
		if (l == r) {
			return Double.MAX_VALUE;
		}
		if (l + 1 == r) {
			return distance(ps[l], ps[r]);
		}
		int center = l + (r - l) / 2;
		double dis1 = minDistance(ps, l, center);
		double dis2 = minDistance(ps, center + 1, r);
		double minDis = min(dis1, dis2);
		ArrayList<Point> nearPoints = new ArrayList<>();
		// 选出距离中间线小于minDis的点
		for (Point p : ps) {
			if (abs(ps[center].x - p.x) <= minDis) {
				nearPoints.add(p);
			}
		}
		// 按照Y轴升序排序
		Collections.sort(nearPoints, new Comparator<Point>() {
			@Override
			public int compare(Point o1, Point o2) {
				if (o1.y < o2.y)
					return -1;
				if (o1.y > o2.y)
					return 1;
				if (o1.x < o2.x)
					return -1;
				if (o1.x > o2.x)
					return 1;
				return 0;
			}
		});
		for (int i = 0; i < nearPoints.size(); i++) {
			for (int j = i + 1; j < nearPoints.size(); j++) {
				if (nearPoints.get(j).y - nearPoints.get(i).y > minDis) {
					break;// 元素y+1离元素i更远,没必要继续比较
				}
				double d = distance(nearPoints.get(j), nearPoints.get(i));
				if (d < minDis) {
					minDis = d;
				}
			}
		}
		return minDis;
	}

	public static double distance(Point p1, Point p2) {
		if (p1 == p2)
			return 0;
		return sqrt(pow(p1.x - p2.x, 2) + pow(p1.y - p2.y, 2));
	}

}


  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值