Как определить вертикальную ось симметрии для списка точек?
Что проверяют
Сумеете ли вы вывести из условия, где может стоять ось, вместо перебора кандидатов, и учтёте ли дубликаты, точки на самой оси и дробные координаты. Следом спрашивают сложность и что меняется для вещественных координат.
Как отвечать
Ключевое наблюдение: крайняя левая и крайняя правая точки обязаны отражаться друг в друга, иначе крайней не найдётся пары. Значит, кандидат на ось ровно один: x = (min_x + max_x) / 2. Остаётся проверить, что у каждой точки (x, y) есть отражение (min_x + max_x - x, y):
def symmetry_axis(points):
if not points:
return None
xs = [x for x, _ in points]
s = min(xs) + max(xs)
seen = set(map(tuple, points))
for x, y in seen:
if (s - x, y) not in seen:
return None
return s / 2Что проговорить:
- сумма вместо середины: сравнение идёт с
s - x, а не с2 * center - x. На целых координатах вся проверка остаётся в целых числах, делится только ответ; - множество: поиск отражения за O(1) в среднем, итого O(n) по времени и O(n) по памяти. Вариант с сортировкой даёт O(n log n);
- точки на оси: отражаются сами в себя, отдельная ветка не нужна;
- дубликаты: множество их схлопывает, это обычная трактовка «набора точек». Если важна кратность, берите
Counterи сравнивайте количества; - вещественные координаты: точное сравнение ненадёжно, их округляют до нужной точности или переводят в целые умножением на масштаб.
Среднее арифметическое x как ось не подходит: дубликаты его смещают, хотя множество точек симметрично.
Где спотыкаются
Перебирают пары точек как кандидатов на ось и получают O(n²) или хуже, хотя кандидат один.
Считают через 2 * center_x - x с плавающей точкой. На целых входах в Python это случайно работает, потому что 3.0 == 3 и хэши у них совпадают, но на дробных координатах сравнение начинает врать.
Проверяют только x и забывают про y. Точки (1, 1) и (3, 5) лежат на равном расстоянии от прямой x = 2, но парой друг другу не являются.