← Назад к вопросам

Четные и нечетные числа

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 comprehensionO(n)O(n)⭐⭐⭐⭐⭐Pythonic
filter()O(n)O(n)⭐⭐⭐⭐Функциональный
Dict результатO(n)O(n)⭐⭐⭐⭐Структурированы
ДетальныйO(n)O(n)⭐⭐⭐Аналитика
In-placeO(n)O(1)⭐⭐⭐Оптимизация
GroupbyO(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: группировка элементов по четности номера
  • Обработка данных: подготовка тестовых данных в две группы
  • Статистика: анализ распределения параметров тестов