ArrayList<Point> points = (ArrayList<Point>)pointsList.clone();
ArrayList<Point> result = new ArrayList<Point>();
// Получаем нижнюю левую точку - первую вершину оболочки - O(n)
Point p0 = getLowestPoint(points);
result.add(p0);
points.remove(p0);
// Получаем последнюю вершину оболочки - O(n)
Point pE = points.get(0);
Point candidate;
for(int i = 1; i < points.size(); i++) {
candidate = points.get(i);
if(crossProduct(p0, candidate, pE) < 0) {
pE = candidate;
}
}
// Строим цепь - O(h) шагов...
Point next = null;
Point last = p0;
do {
// ... на каждом - перебор O(n) точек, итого O(n*h) операций
next = points.get(0);
for(int i = 1; i < points.size(); i++) {
candidate = points.get(i);
if (crossProduct(last, candidate, next) > 0 ||
crossProduct(last, candidate, next) == 0 &&
last.dist(candidate) > last.dist(next)) {
next = candidate;
}
}
result.add(next);