Formatted with Google Java Formatter

This commit is contained in:
github-actions
2020-10-24 10:23:28 +00:00
parent a23bac99e8
commit 5d59a2e828
219 changed files with 13758 additions and 14582 deletions

View File

@@ -1,378 +1,338 @@
package divideconquer;
/**
* For a set of points in a coordinates system (10000 maximum),
* ClosestPair class calculates the two closest points.
* For a set of points in a coordinates system (10000 maximum), ClosestPair class calculates the two
* closest points.
*
* @author: anonymous
* @author: Marisa Afuera
*/
public final class ClosestPair {
/** Number of points */
int numberPoints = 0;
/** Input data, maximum 10000. */
private Location[] array;
/** Minimum point coordinate. */
Location point1 = null;
/** Minimum point coordinate. */
Location point2 = null;
/** Minimum point length. */
private static double minNum = Double.MAX_VALUE;
public static void setMinNum(double minNum) {
ClosestPair.minNum = minNum;
}
public static void setSecondCount(int secondCount) {
ClosestPair.secondCount = secondCount;
}
/** secondCount */
private static int secondCount = 0;
/** Constructor. */
ClosestPair(int points) {
numberPoints = points;
array = new Location[numberPoints];
}
/** Location class is an auxiliary type to keep points coordinates. */
public static class Location {
double x = 0;
double y = 0;
/**
* Number of points
* @param xpar (IN Parameter) x coordinate <br>
* @param ypar (IN Parameter) y coordinate <br>
*/
int numberPoints = 0;
/**
* Input data, maximum 10000.
*/
private Location[] array;
/**
* Minimum point coordinate.
*/
Location point1 = null;
/**
* Minimum point coordinate.
*/
Location point2 = null;
/**
* Minimum point length.
*/
private static double minNum = Double.MAX_VALUE;
public static void setMinNum(double minNum) {
ClosestPair.minNum = minNum;
Location(final double xpar, final double ypar) { // Save x, y coordinates
this.x = xpar;
this.y = ypar;
}
}
public static void setSecondCount(int secondCount) {
ClosestPair.secondCount = secondCount;
}
public Location[] createLocation(int numberValues) {
return new Location[numberValues];
}
/**
* secondCount
*/
private static int secondCount = 0;
public Location buildLocation(double x, double y) {
return new Location(x, y);
}
/**
* Constructor.
*/
ClosestPair(int points) {
numberPoints = points;
array = new Location[numberPoints];
}
/**
* xPartition function: arrange x-axis.
*
* @param a (IN Parameter) array of points <br>
* @param first (IN Parameter) first point <br>
* @param last (IN Parameter) last point <br>
* @return pivot index
*/
public int xPartition(final Location[] a, final int first, final int last) {
/**
* Location class is an auxiliary type to keep points coordinates.
*/
public static class Location {
double x = 0;
double y = 0;
/**
* @param xpar (IN Parameter) x coordinate <br/>
* @param ypar (IN Parameter) y coordinate <br/>
*/
Location(final double xpar, final double ypar) { //Save x, y coordinates
this.x = xpar;
this.y = ypar;
}
}
public Location[] createLocation(int numberValues) {
return new Location[numberValues];
}
public Location buildLocation(double x, double y) {
return new Location(x, y);
}
/**
* xPartition function: arrange x-axis.
*
* @param a (IN Parameter) array of points <br/>
* @param first (IN Parameter) first point <br/>
* @param last (IN Parameter) last point <br/>
* @return pivot index
*/
public int xPartition(
final Location[] a, final int first, final int last) {
Location pivot = a[last]; // pivot
int i = first - 1;
Location temp; // Temporarily store value for position transformation
for (int j = first; j <= last - 1; j++) {
if (a[j].x <= pivot.x) { // Less than or less than pivot
i++;
temp = a[i]; // array[i] <-> array[j]
a[i] = a[j];
a[j] = temp;
}
}
Location pivot = a[last]; // pivot
int i = first - 1;
Location temp; // Temporarily store value for position transformation
for (int j = first; j <= last - 1; j++) {
if (a[j].x <= pivot.x) { // Less than or less than pivot
i++;
temp = a[i]; // array[pivot] <-> array[i]
a[i] = a[last];
a[last] = temp;
return i; // pivot index
temp = a[i]; // array[i] <-> array[j]
a[i] = a[j];
a[j] = temp;
}
}
i++;
temp = a[i]; // array[pivot] <-> array[i]
a[i] = a[last];
a[last] = temp;
return i; // pivot index
}
/**
* yPartition function: arrange y-axis.
*
* @param a (IN Parameter) array of points <br/>
* @param first (IN Parameter) first point <br/>
* @param last (IN Parameter) last point <br/>
* @return pivot index
*/
/**
* yPartition function: arrange y-axis.
*
* @param a (IN Parameter) array of points <br>
* @param first (IN Parameter) first point <br>
* @param last (IN Parameter) last point <br>
* @return pivot index
*/
public int yPartition(final Location[] a, final int first, final int last) {
public int yPartition(
final Location[] a, final int first, final int last) {
Location pivot = a[last]; // pivot
int i = first - 1;
Location temp; // Temporarily store value for position transformation
for (int j = first; j <= last - 1; j++) {
if (a[j].y <= pivot.y) { // Less than or less than pivot
i++;
temp = a[i]; // array[i] <-> array[j]
a[i] = a[j];
a[j] = temp;
}
}
Location pivot = a[last]; // pivot
int i = first - 1;
Location temp; // Temporarily store value for position transformation
for (int j = first; j <= last - 1; j++) {
if (a[j].y <= pivot.y) { // Less than or less than pivot
i++;
temp = a[i]; // array[pivot] <-> array[i]
a[i] = a[last];
a[last] = temp;
return i; // pivot index
temp = a[i]; // array[i] <-> array[j]
a[i] = a[j];
a[j] = temp;
}
}
i++;
temp = a[i]; // array[pivot] <-> array[i]
a[i] = a[last];
a[last] = temp;
return i; // pivot index
}
/**
* xQuickSort function: //x-axis Quick Sorting.
*
* @param a (IN Parameter) array of points <br/>
* @param first (IN Parameter) first point <br/>
* @param last (IN Parameter) last point <br/>
*/
/**
* xQuickSort function: //x-axis Quick Sorting.
*
* @param a (IN Parameter) array of points <br>
* @param first (IN Parameter) first point <br>
* @param last (IN Parameter) last point <br>
*/
public void xQuickSort(final Location[] a, final int first, final int last) {
public void xQuickSort(
final Location[] a, final int first, final int last) {
if (first < last) {
int q = xPartition(a, first, last); // pivot
xQuickSort(a, first, q - 1); // Left
xQuickSort(a, q + 1, last); // Right
}
if (first < last) {
int q = xPartition(a, first, last); // pivot
xQuickSort(a, first, q - 1); // Left
xQuickSort(a, q + 1, last); // Right
}
}
/**
* yQuickSort function: //y-axis Quick Sorting.
*
* @param a (IN Parameter) array of points <br/>
* @param first (IN Parameter) first point <br/>
* @param last (IN Parameter) last point <br/>
*/
/**
* yQuickSort function: //y-axis Quick Sorting.
*
* @param a (IN Parameter) array of points <br>
* @param first (IN Parameter) first point <br>
* @param last (IN Parameter) last point <br>
*/
public void yQuickSort(final Location[] a, final int first, final int last) {
public void yQuickSort(
final Location[] a, final int first, final int last) {
if (first < last) {
int q = yPartition(a, first, last); // pivot
yQuickSort(a, first, q - 1); // Left
yQuickSort(a, q + 1, last); // Right
}
if (first < last) {
int q = yPartition(a, first, last); // pivot
yQuickSort(a, first, q - 1); // Left
yQuickSort(a, q + 1, last); // Right
}
}
/**
* closestPair function: find closest pair.
*
* @param a (IN Parameter) array stored before divide <br/>
* @param indexNum (IN Parameter) number coordinates divideArray <br/>
* @return minimum distance <br/>
*/
/**
* closestPair function: find closest pair.
*
* @param a (IN Parameter) array stored before divide <br>
* @param indexNum (IN Parameter) number coordinates divideArray <br>
* @return minimum distance <br>
*/
public double closestPair(final Location[] a, final int indexNum) {
public double closestPair(final Location[] a, final int indexNum) {
Location[] divideArray = new Location[indexNum];
System.arraycopy(a, 0, divideArray, 0, indexNum); // Copy previous array
int divideX = indexNum / 2; // Intermediate value for divide
Location[] leftArray = new Location[divideX]; //divide - left array
//divide-right array
Location[] rightArray = new Location[indexNum - divideX];
if (indexNum <= 3) { // If the number of coordinates is 3 or less
return bruteForce(divideArray);
}
//divide-left array
System.arraycopy(divideArray, 0, leftArray, 0, divideX);
//divide-right array
System.arraycopy(
divideArray, divideX, rightArray, 0, indexNum - divideX);
double minLeftArea = 0; //Minimum length of left array
double minRightArea = 0; //Minimum length of right array
double minValue = 0; //Minimum lengt
minLeftArea = closestPair(leftArray, divideX); // recursive closestPair
minRightArea = closestPair(rightArray, indexNum - divideX);
// window size (= minimum length)
minValue = Math.min(minLeftArea, minRightArea);
// Create window. Set the size for creating a window
// and creating a new array for the coordinates in the window
for (int i = 0; i < indexNum; i++) {
double xGap = Math.abs(divideArray[divideX].x - divideArray[i].x);
if (xGap < minValue) {
ClosestPair.setSecondCount(secondCount + 1); // size of the array
} else {
if (divideArray[i].x > divideArray[divideX].x) {
break;
}
}
}
// new array for coordinates in window
Location[] firstWindow = new Location[secondCount];
int k = 0;
for (int i = 0; i < indexNum; i++) {
double xGap = Math.abs(divideArray[divideX].x - divideArray[i].x);
if (xGap < minValue) { // if it's inside a window
firstWindow[k] = divideArray[i]; // put in an array
k++;
} else {
if (divideArray[i].x > divideArray[divideX].x) {
break;
}
}
}
yQuickSort(firstWindow, 0, secondCount - 1); // Sort by y coordinates
/* Coordinates in Window */
double length = 0;
// size comparison within window
for (int i = 0; i < secondCount - 1; i++) {
for (int j = (i + 1); j < secondCount; j++) {
double xGap = Math.abs(firstWindow[i].x - firstWindow[j].x);
double yGap = Math.abs(firstWindow[i].y - firstWindow[j].y);
if (yGap < minValue) {
length = Math.sqrt(Math.pow(xGap, 2) + Math.pow(yGap, 2));
// If measured distance is less than current min distance
if (length < minValue) {
// Change minimum distance to current distance
minValue = length;
// Conditional for registering final coordinate
if (length < minNum) {
ClosestPair.setMinNum(length);
point1 = firstWindow[i];
point2 = firstWindow[j];
}
}
} else {
break;
}
}
}
ClosestPair.setSecondCount(0);
return minValue;
Location[] divideArray = new Location[indexNum];
System.arraycopy(a, 0, divideArray, 0, indexNum); // Copy previous array
int divideX = indexNum / 2; // Intermediate value for divide
Location[] leftArray = new Location[divideX]; // divide - left array
// divide-right array
Location[] rightArray = new Location[indexNum - divideX];
if (indexNum <= 3) { // If the number of coordinates is 3 or less
return bruteForce(divideArray);
}
// divide-left array
System.arraycopy(divideArray, 0, leftArray, 0, divideX);
// divide-right array
System.arraycopy(divideArray, divideX, rightArray, 0, indexNum - divideX);
/**
* bruteForce function: When the number of coordinates is less than 3.
*
* @param arrayParam (IN Parameter) array stored before divide <br/>
* @return <br/>
*/
double minLeftArea = 0; // Minimum length of left array
double minRightArea = 0; // Minimum length of right array
double minValue = 0; // Minimum lengt
public double bruteForce(final Location[] arrayParam) {
minLeftArea = closestPair(leftArray, divideX); // recursive closestPair
minRightArea = closestPair(rightArray, indexNum - divideX);
// window size (= minimum length)
minValue = Math.min(minLeftArea, minRightArea);
double minValue = Double.MAX_VALUE; // minimum distance
double length = 0;
double xGap = 0; // Difference between x coordinates
double yGap = 0; // Difference between y coordinates
double result = 0;
if (arrayParam.length == 2) {
// Difference between x coordinates
xGap = (arrayParam[0].x - arrayParam[1].x);
// Difference between y coordinates
yGap = (arrayParam[0].y - arrayParam[1].y);
// distance between coordinates
length = Math.sqrt(Math.pow(xGap, 2) + Math.pow(yGap, 2));
// Conditional statement for registering final coordinate
// Create window. Set the size for creating a window
// and creating a new array for the coordinates in the window
for (int i = 0; i < indexNum; i++) {
double xGap = Math.abs(divideArray[divideX].x - divideArray[i].x);
if (xGap < minValue) {
ClosestPair.setSecondCount(secondCount + 1); // size of the array
} else {
if (divideArray[i].x > divideArray[divideX].x) {
break;
}
}
}
// new array for coordinates in window
Location[] firstWindow = new Location[secondCount];
int k = 0;
for (int i = 0; i < indexNum; i++) {
double xGap = Math.abs(divideArray[divideX].x - divideArray[i].x);
if (xGap < minValue) { // if it's inside a window
firstWindow[k] = divideArray[i]; // put in an array
k++;
} else {
if (divideArray[i].x > divideArray[divideX].x) {
break;
}
}
}
yQuickSort(firstWindow, 0, secondCount - 1); // Sort by y coordinates
/* Coordinates in Window */
double length = 0;
// size comparison within window
for (int i = 0; i < secondCount - 1; i++) {
for (int j = (i + 1); j < secondCount; j++) {
double xGap = Math.abs(firstWindow[i].x - firstWindow[j].x);
double yGap = Math.abs(firstWindow[i].y - firstWindow[j].y);
if (yGap < minValue) {
length = Math.sqrt(Math.pow(xGap, 2) + Math.pow(yGap, 2));
// If measured distance is less than current min distance
if (length < minValue) {
// Change minimum distance to current distance
minValue = length;
// Conditional for registering final coordinate
if (length < minNum) {
ClosestPair.setMinNum(length);
ClosestPair.setMinNum(length);
point1 = firstWindow[i];
point2 = firstWindow[j];
}
point1 = arrayParam[0];
point2 = arrayParam[1];
result = length;
}
} else {
break;
}
if (arrayParam.length == 3) {
for (int i = 0; i < arrayParam.length - 1; i++) {
for (int j = (i + 1); j < arrayParam.length; j++) {
// Difference between x coordinates
xGap = (arrayParam[i].x - arrayParam[j].x);
// Difference between y coordinates
yGap = (arrayParam[i].y - arrayParam[j].y);
// distance between coordinates
length =
Math.sqrt(Math.pow(xGap, 2) + Math.pow(yGap, 2));
// If measured distance is less than current min distance
if (length < minValue) {
// Change minimum distance to current distance
minValue = length;
if (length < minNum) {
// Registering final coordinate
ClosestPair.setMinNum(length);
point1 = arrayParam[i];
point2 = arrayParam[j];
}
}
}
}
result = minValue;
}
}
ClosestPair.setSecondCount(0);
return minValue;
}
/**
* bruteForce function: When the number of coordinates is less than 3.
*
* @param arrayParam (IN Parameter) array stored before divide <br>
* @return <br>
*/
public double bruteForce(final Location[] arrayParam) {
double minValue = Double.MAX_VALUE; // minimum distance
double length = 0;
double xGap = 0; // Difference between x coordinates
double yGap = 0; // Difference between y coordinates
double result = 0;
if (arrayParam.length == 2) {
// Difference between x coordinates
xGap = (arrayParam[0].x - arrayParam[1].x);
// Difference between y coordinates
yGap = (arrayParam[0].y - arrayParam[1].y);
// distance between coordinates
length = Math.sqrt(Math.pow(xGap, 2) + Math.pow(yGap, 2));
// Conditional statement for registering final coordinate
if (length < minNum) {
ClosestPair.setMinNum(length);
}
point1 = arrayParam[0];
point2 = arrayParam[1];
result = length;
}
if (arrayParam.length == 3) {
for (int i = 0; i < arrayParam.length - 1; i++) {
for (int j = (i + 1); j < arrayParam.length; j++) {
// Difference between x coordinates
xGap = (arrayParam[i].x - arrayParam[j].x);
// Difference between y coordinates
yGap = (arrayParam[i].y - arrayParam[j].y);
// distance between coordinates
length = Math.sqrt(Math.pow(xGap, 2) + Math.pow(yGap, 2));
// If measured distance is less than current min distance
if (length < minValue) {
// Change minimum distance to current distance
minValue = length;
if (length < minNum) {
// Registering final coordinate
ClosestPair.setMinNum(length);
point1 = arrayParam[i];
point2 = arrayParam[j];
}
}
}
return result; // If only one point returns 0.
}
result = minValue;
}
return result; // If only one point returns 0.
}
/**
* main function: execute class.
*
* @param args (IN Parameter) <br>
* @throws IOException If an input or output exception occurred
*/
public static void main(final String[] args) {
// Input data consists of one x-coordinate and one y-coordinate
ClosestPair cp = new ClosestPair(12);
cp.array[0] = cp.buildLocation(2, 3);
cp.array[1] = cp.buildLocation(2, 16);
cp.array[2] = cp.buildLocation(3, 9);
cp.array[3] = cp.buildLocation(6, 3);
cp.array[4] = cp.buildLocation(7, 7);
cp.array[5] = cp.buildLocation(19, 4);
cp.array[6] = cp.buildLocation(10, 11);
cp.array[7] = cp.buildLocation(15, 2);
cp.array[8] = cp.buildLocation(15, 19);
cp.array[9] = cp.buildLocation(16, 11);
cp.array[10] = cp.buildLocation(17, 13);
cp.array[11] = cp.buildLocation(9, 12);
System.out.println("Input data");
System.out.println("Number of points: " + cp.array.length);
for (int i = 0; i < cp.array.length; i++) {
System.out.println("x: " + cp.array[i].x + ", y: " + cp.array[i].y);
}
/**
* main function: execute class.
*
* @param args (IN Parameter) <br/>
* @throws IOException If an input or output
* exception occurred
*/
cp.xQuickSort(cp.array, 0, cp.array.length - 1); // Sorting by x value
public static void main(final String[] args) {
double result; // minimum distance
//Input data consists of one x-coordinate and one y-coordinate
ClosestPair cp = new ClosestPair(12);
cp.array[0] = cp.buildLocation(2, 3);
cp.array[1] = cp.buildLocation(2, 16);
cp.array[2] = cp.buildLocation(3, 9);
cp.array[3] = cp.buildLocation(6, 3);
cp.array[4] = cp.buildLocation(7, 7);
cp.array[5] = cp.buildLocation(19, 4);
cp.array[6] = cp.buildLocation(10, 11);
cp.array[7] = cp.buildLocation(15, 2);
cp.array[8] = cp.buildLocation(15, 19);
cp.array[9] = cp.buildLocation(16, 11);
cp.array[10] = cp.buildLocation(17, 13);
cp.array[11] = cp.buildLocation(9, 12);
System.out.println("Input data");
System.out.println("Number of points: " + cp.array.length);
for (int i = 0; i < cp.array.length; i++) {
System.out.println("x: " + cp.array[i].x + ", y: " + cp.array[i].y);
}
cp.xQuickSort(cp.array, 0, cp.array.length - 1); // Sorting by x value
double result; // minimum distance
result = cp.closestPair(cp.array, cp.array.length);
// ClosestPair start
// minimum distance coordinates and distance output
System.out.println("Output Data");
System.out.println("(" + cp.point1.x + ", " + cp.point1.y + ")");
System.out.println("(" + cp.point2.x + ", " + cp.point2.y + ")");
System.out.println("Minimum Distance : " + result);
}
result = cp.closestPair(cp.array, cp.array.length);
// ClosestPair start
// minimum distance coordinates and distance output
System.out.println("Output Data");
System.out.println("(" + cp.point1.x + ", " + cp.point1.y + ")");
System.out.println("(" + cp.point2.x + ", " + cp.point2.y + ")");
System.out.println("Minimum Distance : " + result);
}
}

View File

@@ -5,182 +5,165 @@ import java.util.Comparator;
/**
* @author dimgrichr
* <p>
* Space complexity: O(n)
* Time complexity: O(nlogn), because it is a divide and conquer algorithm
* <p>Space complexity: O(n) Time complexity: O(nlogn), because it is a divide and conquer
* algorithm
*/
public class SkylineAlgorithm {
private ArrayList<Point> points;
private ArrayList<Point> points;
/**
* Main constructor of the application.
* ArrayList points gets created, which represents the sum of all edges.
*/
public SkylineAlgorithm() {
points = new ArrayList<>();
/**
* Main constructor of the application. ArrayList points gets created, which represents the sum of
* all edges.
*/
public SkylineAlgorithm() {
points = new ArrayList<>();
}
/** @return points, the ArrayList that includes all points. */
public ArrayList<Point> getPoints() {
return points;
}
/**
* The main divide and conquer, and also recursive algorithm. It gets an ArrayList full of points
* as an argument. If the size of that ArrayList is 1 or 2, the ArrayList is returned as it is, or
* with one less point (if the initial size is 2 and one of it's points, is dominated by the other
* one). On the other hand, if the ArrayList's size is bigger than 2, the function is called
* again, twice, with arguments the corresponding half of the initial ArrayList each time. Once
* the flashback has ended, the function produceFinalSkyLine gets called, in order to produce the
* final skyline, and return it.
*
* @param list, the initial list of points
* @return leftSkyLine, the combination of first half's and second half's skyline
* @see Point
*/
public ArrayList<Point> produceSubSkyLines(ArrayList<Point> list) {
// part where function exits flashback
int size = list.size();
if (size == 1) {
return list;
} else if (size == 2) {
if (list.get(0).dominates(list.get(1))) {
list.remove(1);
} else {
if (list.get(1).dominates(list.get(0))) {
list.remove(0);
}
}
return list;
}
// recursive part of the function
ArrayList<Point> leftHalf = new ArrayList<>();
ArrayList<Point> rightHalf = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
if (i < list.size() / 2) {
leftHalf.add(list.get(i));
} else {
rightHalf.add(list.get(i));
}
}
ArrayList<Point> leftSubSkyLine = produceSubSkyLines(leftHalf);
ArrayList<Point> rightSubSkyLine = produceSubSkyLines(rightHalf);
/**
* @return points, the ArrayList that includes all points.
*/
public ArrayList<Point> getPoints() {
return points;
// skyline is produced
return produceFinalSkyLine(leftSubSkyLine, rightSubSkyLine);
}
/**
* The first half's skyline gets cleared from some points that are not part of the final skyline
* (Points with same x-value and different y=values. The point with the smallest y-value is kept).
* Then, the minimum y-value of the points of first half's skyline is found. That helps us to
* clear the second half's skyline, because, the points of second half's skyline that have greater
* y-value of the minimum y-value that we found before, are dominated, so they are not part of the
* final skyline. Finally, the "cleaned" first half's and second half's skylines, are combined,
* producing the final skyline, which is returned.
*
* @param left the skyline of the left part of points
* @param right the skyline of the right part of points
* @return left the final skyline
*/
public ArrayList<Point> produceFinalSkyLine(ArrayList<Point> left, ArrayList<Point> right) {
// dominated points of ArrayList left are removed
for (int i = 0; i < left.size() - 1; i++) {
if (left.get(i).x == left.get(i + 1).x && left.get(i).y > left.get(i + 1).y) {
left.remove(i);
i--;
}
}
// minimum y-value is found
int min = left.get(0).y;
for (int i = 1; i < left.size(); i++) {
if (min > left.get(i).y) {
min = left.get(i).y;
if (min == 1) {
i = left.size();
}
}
}
// dominated points of ArrayList right are removed
for (int i = 0; i < right.size(); i++) {
if (right.get(i).y >= min) {
right.remove(i);
i--;
}
}
// final skyline found and returned
left.addAll(right);
return left;
}
public static class Point {
private int x;
private int y;
/**
* The main divide and conquer, and also recursive algorithm.
* It gets an ArrayList full of points as an argument.
* If the size of that ArrayList is 1 or 2,
* the ArrayList is returned as it is, or with one less point
* (if the initial size is 2 and one of it's points, is dominated by the other one).
* On the other hand, if the ArrayList's size is bigger than 2,
* the function is called again, twice,
* with arguments the corresponding half of the initial ArrayList each time.
* Once the flashback has ended, the function produceFinalSkyLine gets called,
* in order to produce the final skyline, and return it.
* The main constructor of Point Class, used to represent the 2 Dimension points.
*
* @param list, the initial list of points
* @return leftSkyLine, the combination of first half's and second half's skyline
* @see Point
* @param x the point's x-value.
* @param y the point's y-value.
*/
public ArrayList<Point> produceSubSkyLines(ArrayList<Point> list) {
// part where function exits flashback
int size = list.size();
if (size == 1) {
return list;
} else if (size == 2) {
if (list.get(0).dominates(list.get(1))) {
list.remove(1);
} else {
if (list.get(1).dominates(list.get(0))) {
list.remove(0);
}
}
return list;
}
// recursive part of the function
ArrayList<Point> leftHalf = new ArrayList<>();
ArrayList<Point> rightHalf = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
if (i < list.size() / 2) {
leftHalf.add(list.get(i));
} else {
rightHalf.add(list.get(i));
}
}
ArrayList<Point> leftSubSkyLine = produceSubSkyLines(leftHalf);
ArrayList<Point> rightSubSkyLine = produceSubSkyLines(rightHalf);
// skyline is produced
return produceFinalSkyLine(leftSubSkyLine, rightSubSkyLine);
public Point(int x, int y) {
this.x = x;
this.y = y;
}
/** @return x, the x-value */
public int getX() {
return x;
}
/** @return y, the y-value */
public int getY() {
return y;
}
/**
* The first half's skyline gets cleared
* from some points that are not part of the final skyline
* (Points with same x-value and different y=values. The point with the smallest y-value is kept).
* Then, the minimum y-value of the points of first half's skyline is found.
* That helps us to clear the second half's skyline, because, the points
* of second half's skyline that have greater y-value of the minimum y-value that we found before,
* are dominated, so they are not part of the final skyline.
* Finally, the "cleaned" first half's and second half's skylines, are combined,
* producing the final skyline, which is returned.
* Based on the skyline theory, it checks if the point that calls the function dominates the
* argument point.
*
* @param left the skyline of the left part of points
* @param right the skyline of the right part of points
* @return left the final skyline
* @param p1 the point that is compared
* @return true if the point wich calls the function dominates p1 false otherwise.
*/
public ArrayList<Point> produceFinalSkyLine(ArrayList<Point> left, ArrayList<Point> right) {
// dominated points of ArrayList left are removed
for (int i = 0; i < left.size() - 1; i++) {
if (left.get(i).x == left.get(i + 1).x && left.get(i).y > left.get(i + 1).y) {
left.remove(i);
i--;
}
}
// minimum y-value is found
int min = left.get(0).y;
for (int i = 1; i < left.size(); i++) {
if (min > left.get(i).y) {
min = left.get(i).y;
if (min == 1) {
i = left.size();
}
}
}
// dominated points of ArrayList right are removed
for (int i = 0; i < right.size(); i++) {
if (right.get(i).y >= min) {
right.remove(i);
i--;
}
}
// final skyline found and returned
left.addAll(right);
return left;
public boolean dominates(Point p1) {
// checks if p1 is dominated
return (this.x < p1.x && this.y <= p1.y) || (this.x <= p1.x && this.y < p1.y);
}
}
public static class Point {
private int x;
private int y;
/**
* The main constructor of Point Class, used to represent the 2 Dimension points.
*
* @param x the point's x-value.
* @param y the point's y-value.
*/
public Point(int x, int y) {
this.x = x;
this.y = y;
}
/**
* @return x, the x-value
*/
public int getX() {
return x;
}
/**
* @return y, the y-value
*/
public int getY() {
return y;
}
/**
* Based on the skyline theory,
* it checks if the point that calls the function dominates the argument point.
*
* @param p1 the point that is compared
* @return true if the point wich calls the function dominates p1
* false otherwise.
*/
public boolean dominates(Point p1) {
// checks if p1 is dominated
return (this.x < p1.x && this.y <= p1.y) || (this.x <= p1.x && this.y < p1.y);
}
}
/**
* It is used to compare the 2 Dimension points,
* based on their x-values, in order get sorted later.
*/
class XComparator implements Comparator<Point> {
@Override
public int compare(Point a, Point b) {
return Integer.compare(a.x, b.x);
}
/**
* It is used to compare the 2 Dimension points, based on their x-values, in order get sorted
* later.
*/
class XComparator implements Comparator<Point> {
@Override
public int compare(Point a, Point b) {
return Integer.compare(a.x, b.x);
}
}
}