获取阵列中所有最近的点

时间:2017-11-01 00:49:43

标签: java arrays algorithm math

我是二维数组,我在其中存储了一些点,以便得到最近的两个点,例如: "( - 1,3),( - 1,-1),(1,1),(2,0.5),(2,-1),(3,3),(4, 2),(4,0.5)" 结果是:"(1.0,1.0)和(2.0,0.5)"  这非常有效:

   Scanner scanner = new Scanner(System.in);
    System.out.println("Enter the number of points");
    int numberOfPoints = scanner.nextInt();

    //setting number of rows, number of column is unable to change
    double[][] points = new double[numberOfPoints][2];
    for (int i = 0; i < points.length; i++) {
        points[i][0] = scanner.nextDouble();
        points[i][1] = scanner.nextDouble();
    }

    int point1 = 0, point2 = 1;
    double shortestDistance = distance(points[point1][0], points[point1][1],
            points[point2][0], points[point2][1]);

    //get shortest distance
    for (int i = 0; i < points.length; i++) {
        for (int j = i + 1; j < points.length; j++) {
            double distance = distance(points[i][0], points[i][1],
                    points[j][0], points[j][1]);

            if (shortestDistance > distance) {

                point1 = i;
                point2 = j;
                shortestDistance = distance;
            }

        }
    }

    System.out.println("The closest two points is" +
            "(" + points[point1][0] + ", " + points[point1][1] + ") and (" +
            points[point2][0] + ", " + points[point2][1] + ")");

}

public static double distance(double x1, double y1, double x2, double y2) {
    return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
}

我试图获得所有最近的点不仅仅是两点。

我试图通过这种方式获得它,但它并不涵盖所有情况并且不会显示所有点:

for (int i = 0; i < points.length; i++) {
        for (int j = 0; j < points.length; j++) {
            if (distance(points[i][0], points[i][1],
                    points[j][0], points[j][1]) == shortestDistance)
                System.out.println("The closest two points are " +
                        "(" + points[i][0] + ", " + points[i][1] + ") and (" +
                        points[j][0] + ", " + points[j][1] + ")");
        }
    }

此外,我尝试初始化新阵列并将距离存储到其中然后对其进行排序,但它失败了。

我如何显示所有最近点?

注意:

我没有发现this question对我有用。

2 个答案:

答案 0 :(得分:0)

以下comment阐明了问题的实际目标:

  

所以你的意思是,当你找到彼此最接近的2个点((1.0, 1.0) - (2.0, 0.5))时,你想要消除它们然后找到下一个&#34;对&#34;那些现在彼此最接近((3.0, 3.0) - (4.0, 2.0)),然后重复((2.0, -1.0) - (4.0, 0.5)),最后得到最后一对((-1.0, 3.0) - (-1.0, -1.0))?

为此,您应首先创建一个Point类,以便轻松跟踪已使用过的点。如果您不想自己编写,可以使用java.awt.geom.Point2D.Double

您还应该创建一个用于跟踪点对的类,以便您可以轻松地按距离对对进行排序。它可以命名为任何名称,但我将其命名为Distance

现在的逻辑是你创建一个包含所有可能的Distance个对象的列表,即成对的点。然后按距离对其进行排序。

第一个列表元素现在是彼此最近的一对。然后迭代列表以找到最接近的下一对点,跳过任何使用已使用点的点。

如果多于一对并且#34;最接近&#34;,则下面的逻辑将选择其中一个。一旦定义了该场景中应该发生的事情,您就可以更改该行为。

public static void main(String[] args) {
    double[][] pointValues = { {-1, 3}, {-1, -1}, {1, 1}, {2, 0.5}, {2, -1}, {3, 3}, {4, 2}, {4, 0.5} };

    Point[] points = new Point[pointValues.length];
    for (int i = 0; i < points.length; i++)
        points[i] = new Point(pointValues[i][0], pointValues[i][1]);

    List<Distance> distances = new ArrayList<>();
    for (int i = 0; i < points.length; i++)
        for (int j = i + 1; j < points.length; j++)
            distances.add(new Distance(points[i], points[j]));
    Collections.sort(distances);

    Set<Point> used = new HashSet<>();
    for (Distance distance : distances) {
        if (! used.contains(distance.getPoint1()) && ! used.contains(distance.getPoint2())) {
            System.out.println(distance);
            used.add(distance.getPoint1());
            used.add(distance.getPoint2());
        }
    }
}
public final class Point {
    private final double x;
    private final double y;
    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }
    public double getX() {
        return this.x;
    }
    public double getY() {
        return this.y;
    }
    @Override
    public String toString() {
        return "(" + this.x + ", " + this.y + ")";
    }
    @Override
    public int hashCode() {
        return Double.hashCode(this.x) * 31 + Double.hashCode(this.y);
    }
    @Override
    public boolean equals(Object obj) {
        if (! (obj instanceof Point))
            return false;
        Point that = (Point) obj;
        return (Double.doubleToLongBits(this.x) == Double.doubleToLongBits(that.x)
             && Double.doubleToLongBits(this.y) == Double.doubleToLongBits(that.y));
    }
}
public final class Distance implements Comparable<Distance> {
    private final Point  p1;
    private final Point  p2;
    private final double distance;
    public Distance(Point p1, Point p2) {
        this.p1 = p1;
        this.p2 = p2;
        this.distance = Math.hypot(p2.getX() - p1.getX(), p2.getY() - p1.getY());
    }
    public Point getPoint1() {
        return this.p1;
    }
    public Point getPoint2() {
        return this.p2;
    }
    public double getDistance() {
        return this.distance;
    }
    @Override
    public String toString() {
        return String.format("%-12s - %-12s: %s", this.p1, this.p2, this.distance);
    }
    @Override
    public int compareTo(Distance that) {
        return Double.compare(this.distance, that.distance);
    }
}

输出

(1.0, 1.0)   - (2.0, 0.5)  : 1.118033988749895
(3.0, 3.0)   - (4.0, 2.0)  : 1.4142135623730951
(2.0, -1.0)  - (4.0, 0.5)  : 2.5
(-1.0, 3.0)  - (-1.0, -1.0): 4.0

答案 1 :(得分:-1)

首先是一个优化技巧:代替距离,使用它的方块(掉根)。

public static double distance2(double x1, double y1, double x2, double y2) {
    return (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
}

取所有最近的点需要维护一个(i,j)列表。

List<int[]> nearestPointIndices = new ArrayList<>();
double shortestDistance2 = Double.MAX_VALUE;

for (int i = 0; i < points.length; i++) {
    for (int j = i + 1; j < points.length; j++) {
        double distance2 = distance2(points[i][0], points[i][1],
                points[j][0], points[j][1]);

        if (shortestDistance2 >= distance2) {
            if (shortestDistance2 > distance2) {
                nearestPointIndices.clear();
                shortestDistance2 = distance2;
            }
            nearestPointIndices.add(new int[] { i, j });
        }
    }
}

那是一个收集最近点(i,j)和最近点的列表 要么在更近点清除该列表,要么在相同的近点清除列表。

另外值得一提的是另一个Math类的功能,如sqrt:

public static double distance(double x1, double y1, double x2, double y2) {
    return Math.hypot((x2 - x1), (y2 - y1)); // Hypotenuse sqrt(a² + b²).
}