← Назад к вопросам
Четные и нечетные числа
2.0 Middle🔥 141 комментариев
#Теория тестирования
Условие
Напишите функцию, которая разделяет массив на два: с четными и нечетными числами.
Пример
Вход: [1, 2, 3, 4, 5, 6] Выход: even=[2, 4, 6], odd=[1, 3, 5]
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Решение: Разделение массива на четные и нечетные числа
Описание проблемы
Нужно разделить массив целых чисел на две группы:
- Четные числа (делятся на 2 без остатка, n % 2 == 0)
- Нечетные числа (дают остаток 1 при делении на 2, n % 2 != 0)
Требования:
- Сохранить исходный порядок элементов
- Вернуть два списка
- Обработать граничные случаи
Подход 1: Простое разделение с двумя списками
def separate_even_odd(arr):
"""
Разделяет массив на четные и нечетные числа.
Args:
arr: List[int] - массив целых чисел
Returns:
tuple: (even_list, odd_list)
"""
even = []
odd = []
for num in arr:
if num % 2 == 0:
even.append(num)
else:
odd.append(num)
return even, odd
# Примеры
even, odd = separate_even_odd([1, 2, 3, 4, 5, 6])
print(f"even={even}, odd={odd}") # even=[2, 4, 6], odd=[1, 3, 5]
even, odd = separate_even_odd([10, 15, 20, 25])
print(f"even={even}, odd={odd}") # even=[10, 20], odd=[15, 25]
Подход 2: List comprehension (Более Pythonic)
def separate_even_odd_v2(arr):
"""
Использует list comprehension для более лаконичного кода.
"""
even = [x for x in arr if x % 2 == 0]
odd = [x for x in arr if x % 2 != 0]
return even, odd
even, odd = separate_even_odd_v2([1, 2, 3, 4, 5, 6])
print(f"even={even}, odd={odd}") # even=[2, 4, 6], odd=[1, 3, 5]
Подход 3: Использование filter()
def separate_even_odd_v3(arr):
"""
Использует встроенную функцию filter.
Функциональный подход.
"""
even = list(filter(lambda x: x % 2 == 0, arr))
odd = list(filter(lambda x: x % 2 != 0, arr))
return even, odd
even, odd = separate_even_odd_v3([1, 2, 3, 4, 5, 6])
print(f"even={even}, odd={odd}") # even=[2, 4, 6], odd=[1, 3, 5]
Подход 4: Возвращение словаря
def separate_even_odd_dict(arr):
"""
Возвращает результат в виде словаря.
Удобно для более сложных обработок.
"""
return {
'even': [x for x in arr if x % 2 == 0],
'odd': [x for x in arr if x % 2 != 0]
}
result = separate_even_odd_dict([1, 2, 3, 4, 5, 6])
print(result) # {'even': [2, 4, 6], 'odd': [1, 3, 5]}
print(f"Четные: {result['even']}, Нечетные: {result['odd']}")
Подход 5: С дополнительной информацией
def separate_even_odd_detailed(arr):
"""
Возвращает разделённые числа и статистику.
"""
even = [x for x in arr if x % 2 == 0]
odd = [x for x in arr if x % 2 != 0]
return {
'even': even,
'odd': odd,
'even_count': len(even),
'odd_count': len(odd),
'even_sum': sum(even),
'odd_sum': sum(odd),
'even_avg': sum(even) / len(even) if even else 0,
'odd_avg': sum(odd) / len(odd) if odd else 0
}
result = separate_even_odd_detailed([1, 2, 3, 4, 5, 6])
print(f"Четные: {result['even']}")
print(f"Количество четных: {result['even_count']}")
print(f"Сумма четных: {result['even_sum']}")
print(f"Среднее четных: {result['even_avg']}")
Подход 6: In-place разделение (Оптимизация памяти)
def separate_even_odd_inplace(arr):
"""
Разделяет массив in-place используя два указателя.
Модифицирует исходный массив.
Временная сложность: O(n)
Пространственная сложность: O(1)
"""
left = 0
right = len(arr) - 1
while left < right:
# Ищем нечетное слева
while left < right and arr[left] % 2 == 0:
left += 1
# Ищем четное справа
while left < right and arr[right] % 2 != 0:
right -= 1
# Swap
if left < right:
arr[left], arr[right] = arr[right], arr[left]
left += 1
right -= 1
# Находим точку разделения
split_point = 0
for i in range(len(arr)):
if arr[i] % 2 == 0:
split_point = i
break
return arr[:split_point], arr[split_point:]
arr = [1, 2, 3, 4, 5, 6]
even, odd = separate_even_odd_inplace(arr)
print(f"even={even}, odd={odd}")
Подход 7: Использование groupby
from itertools import groupby
def separate_even_odd_groupby(arr):
"""
Использует itertools.groupby для группировки.
Требует отсортированный массив!
"""
sorted_arr = sorted(arr, key=lambda x: x % 2)
result = {}
for key, group in groupby(sorted_arr, key=lambda x: x % 2 == 0):
result['even' if key else 'odd'] = list(group)
return result.get('even', []), result.get('odd', [])
even, odd = separate_even_odd_groupby([1, 2, 3, 4, 5, 6])
print(f"even={even}, odd={odd}") # even=[2, 4, 6], odd=[1, 3, 5]
Сравнение подходов
| Подход | Время | Память | Читаемость | Использование |
|---|---|---|---|---|
| Два списка | O(n) | O(n) | ⭐⭐⭐⭐⭐ | Стандарт |
| List comprehension | O(n) | O(n) | ⭐⭐⭐⭐⭐ | Pythonic |
| filter() | O(n) | O(n) | ⭐⭐⭐⭐ | Функциональный |
| Dict результат | O(n) | O(n) | ⭐⭐⭐⭐ | Структурированы |
| Детальный | O(n) | O(n) | ⭐⭐⭐ | Аналитика |
| In-place | O(n) | O(1) | ⭐⭐⭐ | Оптимизация |
| Groupby | O(n log n) | O(n) | ⭐⭐⭐ | Специальные |
Граничные случаи и тестирование
def test_separate_even_odd():
test_cases = [
([1, 2, 3, 4, 5, 6], [2, 4, 6], [1, 3, 5]),
([1, 3, 5], [], [1, 3, 5]),
([2, 4, 6], [2, 4, 6], []),
([], [], []),
([0], [0], []),
([-1, -2, -3, -4], [-2, -4], [-1, -3]),
([10], [10], []),
]
for arr, expected_even, expected_odd in test_cases:
even, odd = separate_even_odd_v2(arr)
assert even == expected_even, f"Even: {even} != {expected_even}"
assert odd == expected_odd, f"Odd: {odd} != {expected_odd}"
print(f"✓ {arr} -> even={even}, odd={odd}")
test_separate_even_odd()
Анализ сложности
Временная: O(n) — требуется пройти по всем элементам один раз Пространственная: O(n) — новые списки содержат все элементы
Исключение: in-place подход O(1) дополнительной памяти
Практическое применение в QA Automation
- Разделение тест-кейсов: четные для одной среды, нечетные для другой
- Балансировка нагрузки: распределение тестов на разные агенты
- Аналитика результатов: разделение успешных и неудачных тестов
- Работа с ID: группировка элементов по четности номера
- Обработка данных: подготовка тестовых данных в две группы
- Статистика: анализ распределения параметров тестов