← Назад к вопросам
Пересечение двух списков
1.0 Junior🔥 201 комментариев
#Python Core
Условие
Напишите функцию, которая возвращает пересечение двух списков (элементы, присутствующие в обоих).
Пример
intersection([1, 2, 3, 4], [3, 4, 5, 6]) → [3, 4] intersection([1, 2], [3, 4]) → []
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Пересечение двух списков
Задача: найти элементы, которые присутствуют в обоих списках. Это классическая задача обработки данных, часто встречается в алгоритмических интервью.
Решение 1: Использование множеств
def intersection(list1, list2):
"""Найти пересечение двух списков через множества."""
return list(set(list1) & set(list2))
# Примеры
print(intersection([1, 2, 3, 4], [3, 4, 5, 6])) # [3, 4]
print(intersection([1, 2], [3, 4])) # []
print(intersection([1, 1, 2, 2], [1, 2, 2, 3])) # [1, 2]
Решение 2: Сохранение порядка (list comprehension)
def intersection_v2(list1, list2):
"""Найти пересечение, сохраняя порядок из list1."""
set2 = set(list2)
return [x for x in list1 if x in set2]
# Примеры
print(intersection_v2([1, 2, 3, 4], [3, 4, 5, 6])) # [1, 2, 3, 4]
print(intersection_v2([4, 3, 2, 1], [3, 4, 5, 6])) # [4, 3]
print(intersection_v2([1, 2], [3, 4])) # []
Решение 3: Без дубликатов в результате
def intersection_v3(list1, list2):
"""Найти пересечение без дубликатов, сохраняя порядок."""
set2 = set(list2)
result = []
seen = set()
for x in list1:
if x in set2 and x not in seen:
result.append(x)
seen.add(x)
return result
# Примеры
print(intersection_v3([1, 1, 2, 2], [1, 2, 2, 3])) # [1, 2]
print(intersection_v3([1, 2, 3, 3, 4], [2, 3, 3, 5])) # [2, 3]
Решение 4: Двойной цикл (без дополнительной памяти)
def intersection_v4(list1, list2):
"""Найти пересечение через вложенные циклы."""
result = []
for x in list1:
if x in list2:
result.append(x)
return list(set(result)) # Удаляем дубликаты
# Примеры
print(intersection_v4([1, 2, 3, 4], [3, 4, 5, 6])) # [3, 4]
print(intersection_v4([1, 1, 2, 2], [1, 2, 2, 3])) # [1, 2]
Решение 5: Встроенный метод (если списки — это множества)
def intersection_v5(list1, list2):
"""Использование встроенного метода множеств."""
return list(set(list1).intersection(set(list2)))
# Эквивалентно первому решению
print(intersection_v5([1, 2, 3, 4], [3, 4, 5, 6])) # [3, 4]
Сравнение подходов
import timeit
list1 = list(range(10000))
list2 = list(range(5000, 15000))
# Способ 1: set() & set()
time1 = timeit.timeit(
lambda: list(set(list1) & set(list2)),
number=1000
)
# Способ 2: list comprehension с set
time2 = timeit.timeit(
lambda: [x for x in list1 if x in set(list2)],
number=1000
)
# Способ 3: double loop + set
time3 = timeit.timeit(
lambda: list(set([x for x in list1 if x in list2])),
number=1000
)
print(f"set() & set(): {time1:.4f} сек")
print(f"list comprehension: {time2:.4f} сек")
print(f"double loop: {time3:.4f} сек")
print("\nВывод: Использование множеств & множества — наиболее эффективно")
Обработка граничных случаев
def test_intersection():
test_cases = [
([1, 2, 3, 4], [3, 4, 5, 6], [3, 4]),
([1, 2], [3, 4], []),
([], [1, 2, 3], []),
([1, 2, 3], [], []),
([], [], []),
([1, 1, 2, 2], [1, 2, 2, 3], [1, 2]),
([1], [1], [1]),
([1], [2], []),
([1, 2, 3], [1, 2, 3], [1, 2, 3]),
]
for list1, list2, expected_set in test_cases:
result = list(set(list1) & set(list2))
result_set = set(result)
expected_set = set(expected_set)
assert result_set == expected_set, f"Ошибка: intersection({list1}, {list2}) = {result}, ожидается {list(expected_set)}"
print(f"✓ intersection({list1}, {list2}) = {sorted(result)}")
print("\nВсе тесты пройдены!")
test_intersection()
Продвинутые варианты
Пересечение множества списков
def intersection_multiple(*lists):
"""Найти пересечение нескольких списков."""
if not lists:
return []
result = set(lists[0])
for lst in lists[1:]:
result &= set(lst)
return list(result)
# Примеры
print(intersection_multiple([1, 2, 3], [2, 3, 4], [2, 3, 5])) # [2, 3]
print(intersection_multiple([1, 2, 3])) # [1, 2, 3]
print(intersection_multiple()) # []
С сохранением дубликатов
from collections import Counter
def intersection_with_duplicates(list1, list2):
"""Найти пересечение с учётом количества дубликатов."""
count1 = Counter(list1)
count2 = Counter(list2)
result = []
for elem in count1:
if elem in count2:
result.extend([elem] * min(count1[elem], count2[elem]))
return result
# Примеры
print(intersection_with_duplicates([1, 1, 2, 2], [1, 2, 2, 3])) # [1, 2, 2]
print(intersection_with_duplicates([1, 1, 1], [1, 1])) # [1, 1]
Пересечение отсортированных массивов
def intersection_sorted(list1, list2):
"""Оптимизированное пересечение для отсортированных списков."""
result = []
i, j = 0, 0
while i < len(list1) and j < len(list2):
if list1[i] == list2[j]:
result.append(list1[i])
i += 1
j += 1
elif list1[i] < list2[j]:
i += 1
else:
j += 1
return result
# Примеры (массивы должны быть отсортированы)
print(intersection_sorted([1, 2, 3, 4], [2, 3, 4, 5])) # [2, 3, 4]
print(intersection_sorted([1], [1])) # [1]
Анализ сложности
"""
Метод 1: set() & set()
- Временная сложность: O(n + m) где n и m — размеры списков
- Пространственная сложность: O(min(n, m))
- Быстро, хорошо работает на больших данных
Метод 2: list comprehension с set
- Временная сложность: O(n) где n — размер первого списка
- Пространственная сложность: O(m) для множества
- Сохраняет порядок из первого списка
Метод 3: двойной цикл
- Временная сложность: O(n * m) — могла быть O(n) с оптимизацией
- Пространственная сложность: O(1) дополнительно
- Медленнее на больших данных
Метод 4: отсортированные массивы
- Временная сложность: O(n + m)
- Пространственная сложность: O(1) если не считать результат
- Только если массивы уже отсортированы
"""
Рекомендации
- Для большинства случаев: используйте
set() & set()илиset(list1).intersection(set(list2)) - Если важен порядок: используйте list comprehension с set2
- Для учебных целей: рассмотрите двойной цикл (O(n*m))
- Для больших отсортированных данных: используйте двухточечный метод
# Финальное рекомендуемое решение
def intersection(list1, list2):
"""Найти пересечение двух списков."""
return list(set(list1) & set(list2))
# Или с сохранением порядка
def intersection_ordered(list1, list2):
"""Найти пересечение, сохраняя порядок из list1."""
set2 = set(list2)
return [x for x in list1 if x in set2]