Skip to content

Instantly share code, notes, and snippets.

@guliash
Created December 24, 2015 19:58
Show Gist options
  • Save guliash/317557420f23ad4afd9a to your computer and use it in GitHub Desktop.
Save guliash/317557420f23ad4afd9a to your computer and use it in GitHub Desktop.
public ArrayDeque<PairInt> findPoints(PairInt[] points) {
ArrayDeque<PairInt> result = new ArrayDeque<>();
int n = points.length;
int val, j;
int leftBorder, rightBorder;
leftBorder = Integer.MAX_VALUE;
rightBorder = Integer.MIN_VALUE;
Arrays.sort(points, new Comparator<PairInt>() {
@Override
public int compare(PairInt o1, PairInt o2) {
if(o1.y == o2.y) {
return o1.x - o2.x;
}
return o2.y - o1.y;
}
});
for(int i = 0; i < n;) {
val = points[i].y;
j = i;
for(; j < n && points[j].y == val; j++) {} //ищем следующие максимальные по высоте точки
if(points[i].x < leftBorder) {
//самая левая из этих точек points[i]
result.addFirst(new PairInt(leftBorder, val));
result.addFirst(points[i]);
leftBorder = points[i].x;
}
if(points[j - 1].x > rightBorder) {
//самая правая из этих точек points[j - 1]
result.addLast(new PairInt(rightBorder, val));
result.addLast(points[j - 1]);
rightBorder = points[j - 1].x;
}
i = j;
}
return result;
}
@guliash
Copy link
Author

guliash commented Dec 24, 2015

Я предложу несколько иное решение.

Визуально его можно представить следующим образом. Пусть у нас есть пластина какого-то материала. Мы её горизонтально сверху бросаем на нашу фигуру. При встрече с фигурой, она разломится соприкоснувшись с самыми высокими точками следующим образом: найдём самую высокую точку слева и справа, кусок пластины между точками останется лежать на них, а куски по краям полетят дальше вниз. Дальше эти кусочки снова встретятся с другими следующими самыми высокими точками и т.п.. Фигура полученная вот этими кусками и есть искомый забор сверху. Делаем тоже самое для других сторон.
Как это сделать алгоритмически. Рассмотрим случай сверху:
Сортируем точки по убыванию y, а в случае равенства по возрастанию x.
Будем также поддерживать левую и правую границу по x крайних последних разломов.
Далее в цикле слева направо, переходим от уровня к уровню по y, проверяем есть ли разломы за пределами границ и меняем границы.
Можно обобщить этот метод и для нижней стороны.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment