возникла небольшая проблема. Написал программу, которая ищет 2 ближайшие точки 2-мя методами: декомпозиции и полным перебором. Из теории мне известно, что время работы метода грубой силы O(n^2), а метода декомпозиции О(nlogn). Но при реализации программы, сравнивая время, получается, что сколько бы точек я не брал, разница всегда +- в m раз. Можете ли подсказать в чем может быть дело? Что-то в программе?
import static java.lang.Math.sqrt;
import java.util.ArrayList;
public class BruteFindClosestPoints {
int index1 = -1;
int index2 = -1;
double min;
double BruteFindClosestPoints(ArrayList<Point> arrayPoint) {
min = Integer.MAX_VALUE;
double d;
for (int i = 0; i < arrayPoint.size() - 1; i++) {
for (int j = i + 1; j < arrayPoint.size()&&j!=i; j++) {
d = Math.pow((arrayPoint.get(j).X - arrayPoint.get(i).X), 2)
+ (Math.pow((arrayPoint.get(j).Y - arrayPoint.get(i).Y), 2));
if (d < min) {
min = d;
index1 = arrayPoint.get(i).getID();
index2 = arrayPoint.get(j).getID();
}
}
}
min = sqrt(min);
return min;
}
public int getIndex1() {
return index1;
}
public int getIndex2() {
return index2;
}
void show() {
System.out.println("Ближайшие точки (BruteForce): " + (index1) + " и " + (index2) + " с расстоянием: " + min);
}
}
Дальше метод декомпозиции:
import static java.lang.Math.abs;
import static java.lang.Math.sqrt;
import java.util.ArrayList;
public class DecompositionFindClosestPoints {
int index1 = -1, index2 = -1;
int index3 = -1, index4 = -1;
double m = Integer.MAX_VALUE;
double DecompositionFindClosestPoints(ArrayList<Point> pointSortedX, ArrayList<Point> pointSortedY) {
int lgth = pointSortedX.size();
if (lgth <= 3) {
BruteFindClosestPoints a = new BruteFindClosestPoints();
double dist = a.BruteFindClosestPoints(pointSortedX);
index1 = a.getIndex1();
index2 = a.getIndex2();
return dist;
}
int mid = lgth / 2;
Point midPoint = new Point(pointSortedX.get(mid));
ArrayList<Point> Pxl = new ArrayList<>(pointSortedX.subList(0, mid + 1));
ArrayList<Point> Pxr = new ArrayList<>(pointSortedX.subList(mid + 1, lgth));
ArrayList<Point> Pyl = new ArrayList<>();
ArrayList<Point> Pyr = new ArrayList<>();
for (int i = 0; i < lgth; i++) {
if (pointSortedY.get(i).getX() <= midPoint.getX()) {
Pyl.add(pointSortedY.get(i));
} else {
Pyr.add(pointSortedY.get(i));
}
}
DecompositionFindClosestPoints dl_ = new DecompositionFindClosestPoints();
DecompositionFindClosestPoints dr_ = new DecompositionFindClosestPoints();
double dl = dl_.DecompositionFindClosestPoints(Pxl, Pyl);
double dr = dr_.DecompositionFindClosestPoints(Pxr, Pyr);
double d;
if (dl < dr) {
index1 = dl_.getIndex1();
index2 = dl_.getIndex2();
d = dl;
} else {
index1 = dr_.getIndex1();
index2 = dr_.getIndex2();
d = dr;
}
ArrayList<Point> strip = new ArrayList<>();
for (int i = 0; i < pointSortedY.size(); i++) {
if (abs(pointSortedY.get(i).getX() - midPoint.getX()) < min(d, m)) {
strip.add(pointSortedY.get(i));
}
}
double dist = stripClosest(strip, d, Pxl, Pxr);
if (dist < d) {
index1 = index3;
index2 = index4;
m = dist;
} else {
m = d;
}
return m;
}
double stripClosest(ArrayList<Point> a, double d, ArrayList<Point> Pxl, ArrayList<Point> Pxr) {
double min = d;
double dist;
for (int i = 0; i < a.size() - 1; i++) {
for (int j = i + 1; j < a.size(); j++) {
if (a.get(j).getY() - a.get(i).getY() < min) {
if (!(Pxl.contains(a.get(j)) && Pxl.contains(a.get(i)))
|| !(Pxr.contains(a.get(i)) && Pxr.contains(a.get(j)))) {
dist = sqrt(Math.pow((a.get(j).X - a.get(i).X), 2)
+ (Math.pow((a.get(j).Y - a.get(i).Y), 2)));
if (dist < min) {
min = dist;
index3 = a.get(i).getID();
index4 = a.get(j).getID();
}
} else {
}
} else {
j = a.size();
}
}
}
return min;
}
public int getIndex1() {
return index1;
}
public int getIndex2() {
return index2;
}
void show() {
System.out.println("Ближайшие точки (Decomposition): " + (index1) + " и " + (index2) + " с расстоянием: " + m);
}
double min(double x, double y) {
return (x < y) ? x : y;
}
}
Главный класс:
import java.awt.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Random;
public class FindPoint {
public static void main(String[] args) {
long averageTimeDecomposition = 0;
long averageTimeBrute = 0;
for (int j = 0; j < 10; j++) {
ArrayList<Point> point = new ArrayList<>();
int min = 0;
int max = 100;
HashSet<Integer> ptX = new HashSet<>();
for (int i = 0; i < 10; i++) {
Random rnd = new Random();
int rndX = min + rnd.nextInt(max - min + 1);
int rndY = min + rnd.nextInt(max - min + 1);
if (!ptX.contains(rndX)) {
ptX.add(rndX);
point.add(new Point(rndX, rndY, point.size()));
System.out.println(point.size() + ": " + " X: " + rndX + " Y: " + rndY);
} else {
i--;
}
}
double check1;
double check2;
long startTime = System.nanoTime();
BruteFindClosestPoints a = new BruteFindClosestPoints();
check1 = a.BruteFindClosestPoints(point);
a.show();
averageTimeBrute += System.nanoTime() - startTime;
Collections.sort(point, Point.COMPARE_BY_X);
ArrayList pointX = new ArrayList<>(point);
Collections.sort(point, Point.COMPARE_BY_Y);
ArrayList pointY = new ArrayList<>(point);
startTime = System.nanoTime();
DecompositionFindClosestPoints b = new DecompositionFindClosestPoints();
check2 = b.DecompositionFindClosestPoints(pointX, pointY);
averageTimeDecomposition += System.nanoTime() - startTime;
b.show();
System.out.println("---------------------------------------");
}
System.out.println("Среднее время грубый: " + (averageTimeBrute / 1000));
System.out.println("Среднее время декомпозиции: " + (averageTimeDecomposition / 1000));
}
} И последний класс:
import java.util.Comparator;
import java.util.Random;
public class Point {
int X;
int Y;
int id;
public Point(int X, int Y, int id) {
this.X = X;
this.Y = Y;
this.id = id;
}
public Point(Point a) {
this.X = a.getX();
this.Y = a.getY();
this.id = a.getID();
}
public Point(int id) {
Random random = new Random();
this.X = random.nextInt();
this.Y = random.nextInt();
this.id = id;
}
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 int getID() {
return id;
}
public void setID(int id) {
this.id = id;
}
public static final Comparator<Point> COMPARE_BY_X = new Comparator<Point>() {
@Override
public int compare(Point a, Point b) {
return a.getX() - b.getX();
}
};
public static final Comparator<Point> COMPARE_BY_Y = new Comparator<Point>() {
@Override
public int compare(Point a, Point b) {
return a.getY() - b.getY();
}
};
@Override
public String toString() {
return "Point{" + "X=" + X + ", Y=" + Y + ", id=" + id + '}';
}
}
Код не смотрел, но сразу можно отметить, что сложность алгоритма не стоит ассоциировать со временем выполнения. Метод декомпозиции даже визуально выглядит сложнее.
Самое главное, зачем пишу. В Java не так просто замерить время выполнения. За кадром работает операционка с другими процессами, Garbage Collector, кроме того, в какой-то момент времени горячие участки кода компилируются, а часть кода, которая, как кажется JVM бесполезная, попросту может не выполняться.
Вот небольшое обсуждение, где всё это рассматривается немного подробнее: https://javatalks.ru/topics/26726
Тут пример, как можно замерить точнее: https://habr.com/ru/post/349914/
Тонкостей на самом деле много, с ходу не могу найти ссылку на материал, где все нюансы описаны в полной мере.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Создаю приложение на микросервисной архитектуре с использованием Spring Boot, Spring CloudКак пример я смотрю вот этот репозиторий
Необходимо по таймеру увеличивать и уменьшать сферу например за 5 секунд увеличить и за 5 секунд уменьшить, этот код работает, ну я не знаю...
Есть старый проект(xul, tomcat 5, jdk 15, hibernate, firebird и т