Как вычислить симметричную точку без сортировки?
Что проверяют
Под этой формулировкой обычно скрывается задача про отражение точек: дан набор точек на плоскости, нужно понять, существует ли вертикальная прямая, относительно которой он симметричен. Проверяют, догадаетесь ли вы найти ось сразу, без сортировки, и заменить поиск пар множеством. Следом спрашивают про сложность и дубликаты.
Как отвечать
Если ось существует, она проходит ровно посередине между крайними точками. Точке (x, y) соответствует отражение (2c-x, y), где c это середина. Чтобы не связываться с дробями, берут сумму s = min_x + max_x и ищут пару (s-x, y):
def is_reflected(points: list[tuple[int, int]]) -> bool:
if not points:
return True
xs = [x for x, _ in points]
s = min(xs) + max(xs)
seen = set(points)
return all((s-x, y) in seen for x, y in seen)Разбор по шагам:
- ось без сортировки:
minиmaxнаходятся за один проход, O(n). Сортировка дала бы O(n log n) и ничего не добавила; - множество вместо поиска пары: проверка
inдляsetв среднем O(1), весь алгоритм O(n) по времени и O(n) по памяти; - дубликаты:
set(points)схлопывает одинаковые точки, повторы не ломают проверку; - точки на оси: при
x == s-xточка отражается сама в себя и проходит проверку без особого случая.
Если спросили отражение одной точки относительно другой, формула та же: 2c-p по каждой координате. Тогда стоит сразу уточнить условие, это ценится само по себе.
Где спотыкаются
Сравнивают дробные координаты через множество. 0.1 + 0.2 не равно 0.3, и пара не находится. Если на входе float, координаты приводят к целым масштабированием или округляют до оговорённой точности.
Ищут пару для каждой точки перебором по списку. Выходит O(n²), ровно то, от чего задача уводит.
Не уточняют условие: сколько измерений, бывает ли пустой набор, считаются ли совпадающие точки разными. В последнем случае set уже не подходит, пары считают через collections.Counter.