PrepBro
Профессии
PrepBro
Профессия:

Подготовка

  • Вопросы1272
  • Задачи91

Аналитика

  • hh статистика
  • Анализ резюме

Практика

  • Тестовое собеседование
  • Mock-собеседование
  • Менторы

Поддержка / отзывы

Telegram админа
Профессия:

Подготовка

  • Вопросы1272
  • Задачи91

Аналитика

  • hh статистика
  • Анализ резюме

Практика

  • Тестовое собеседование
  • Mock-собеседование
  • Менторы

Поддержка / отзывы

Telegram админа
Все 24 профессии
Android DeveloperData AnalystSystem Analyst1С DeveloperiOS DeveloperBusiness AnalystJava DeveloperData ScientistQA EngineerQA AutomationPHP BackendC/C++ BackendDevOps EngineerIT Project ManagerFrontend DeveloperNode.js BackendUnity DeveloperC# BackendProduct AnalystFlutter DeveloperPython DeveloperIT Product ManagerGo DeveloperData Engineer

© 2026 PrepBro. Все права защищены.

Telegram-бот

Задачи по QA Automation

Задачи с собеседований на автоматизатора тестирования: автотест на pytest, тест формы регистрации, вход в систему, CSS-селекторы, SQL-запросы с JOIN и поиском дубликатов, алгоритмы на строках и массивах. К каждой задаче приложен разбор с кодом решения.

Проверка на подстроку
2.3 Middle🔥 20💬 1

Решение: Алгоритм поиска подстроки без встроенных методов

Подход

Для поиска подстроки в строке без встроенных методов используются два основных алгоритма: наивный и эффективный (KMP). Здесь представлены обе реализации с объяснением.

1. Наивный алгоритм O(n*m)

Проверяем каждую позицию в основной строке и сравниваем посимвольно.

def strStr_naive(haystack: str, needle: str) -> int:
    """
    Наивный поиск подстроки.
    Time: O(n*m) где n=len(haystack), m=len(needle)
    Space: O(1)
    """
    if not needle:
        return 0
    
    if len(needle) > len(haystack):
        return -1
    
    for i in range(len(haystack) - len(needle) + 1):
        # Проверяем совпадение на позиции i
        match = True
        for j in range(len(needle)):
            if haystack[i + j] != needle[j]:
                match = False
                break
        
        if match:
            return i
    
    return -1

2. KMP алгоритм O(n+m)

Читать полностью ->
Нахождение медианы двух отсортированных массивов
2.3 Middle🔥 20💬 1

Решение

Понимание задачи

Найти медиану двух отсортированных массивов. Медиана — среднее значение в объединённом отсортированном массиве.

Простое решение: Объединение и сортировка

def find_median(nums1, nums2):
    merged = sorted(nums1 + nums2)
    n = len(merged)
    if n % 2 == 1:
        return float(merged[n // 2])
    else:
        return (merged[n // 2 - 1] + merged[n // 2]) / 2.0

Примеры:

  • [1, 3] и [2] -> [1, 2, 3] -> медиана 2.0
  • [1, 2] и [3, 4] -> [1, 2, 3, 4] -> медиана (2+3)/2 = 2.5

Сложность

  • Временная: O((m+n) log (m+n))
  • Пространственная: O(m+n)

Оптимальное решение: Двухуказатель

Читать полностью ->
Сложение двух связных списков
2.2 Middle🔥 20💬 1

Решение: Сложение двух связных списков

Эта задача требует работы со связными списками. Ключевой момент — цифры хранятся в обратном порядке, что упрощает сложение (начинаем с младших разрядов).

Алгоритм решения

  1. Создаём новый связный список для результата
  2. Инициализируем переменную переноса (carry) = 0
  3. Проходим по обоим спискам одновременно:
    • Берём значение из первого списка (или 0, если список закончился)
    • Берём значение из второго списка (или 0, если список закончился)
    • Складываем оба значения + carry из предыдущей итерации
    • Новая цифра = сумма % 10
    • Новый carry = сумма // 10
    • Добавляем новый узел в результирующий список
  4. Если после окончания списков остался carry — добавляем его в результат
  5. Возвращаем результирующий список

Структура узла списка

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

Реализация решения

Читать полностью ->
Преобразование числа в римское
2.0 Middle🔥 20💬 1

Решение

Понимание задачи

Преобразовать целое число (1-3999) в римскую запись. Используется принцип вычитания: V (5) перед X (10) означает 4, а не 15.

Оптимальный алгоритм: Greedy с таблицей значений

def int_to_roman(num):
    """
    Преобразует число в римскую запись.
    """
    # Таблица (значение, символ) отсортирована по убыванию
    values = [
        (1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD'),
        (100, 'C'), (90, 'XC'), (50, 'L'), (40, 'XL'),
        (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I')
    ]
    
    result = ''
    for value, symbol in values:
        count = num // value
        if count:
            result += symbol * count
            num -= value * count
    
    return result

Как это работает

Пример: 1994

Шаг 1: 1994 / 1000 = 1 -> 'M', остаток 994 Шаг 2: 994 / 900 = 1 -> 'CM', остаток 94 Шаг 3: 94 / 90 = 1 -> 'XC', остаток 4 Шаг 4: 4 / 4 = 1 -> 'IV', остаток 0

Результат: 'MCMXCIV'

Сложность

Читать полностью ->
Частота символов в строке
1.7 Middle🔥 20💬 1

Решение задачи "Частота символов в строке"

Для подсчёта частоты символов в строке я реализую функцию, которая принимает строку в качестве входного параметра и возвращает словарь (или аналогичную структуру данных), где ключами являются символы, а значениями — количество их вхождений в строке. Рассмотрю несколько подходов к решению, их плюсы и минусы, а также приведу реализацию на Python.

Основные подходы к решению

  1. Использование словаря (hash map) — классический и наиболее эффективный способ для данной задачи.
  2. Использование collections.Counter — встроенный инструмент Python, который упрощает код.
  3. Использование массива/списка для ASCII символов — подходит, если работа ведётся только с символами из определённого диапазона (например, ASCII).

Реализация на Python

Способ 1: Использование обычного словаря

Этот подход универсален и подходит для любых символов, включая Unicode.

Читать полностью ->
Сумма элементов массива
2.0 Middle🔥 20💬 1

Решение

Понимание задачи

Нужно найти сумму всех элементов массива без использования встроенной функции sum(). Это базовая операция, но важная для тестирования и разработки.

Основное решение: Итерация с циклом

def array_sum(arr):
    """
    Находит сумму всех элементов массива без sum().
    """
    total = 0
    for num in arr:
        total += num
    return total

# Использование
result = array_sum([1, 2, 3, 4, 5])
print(result)  # 15

Как это работает

Пошаговое выполнение:

Шаг 0: total = 0
Шаг 1: total = 0 + 1 = 1
Шаг 2: total = 1 + 2 = 3
Шаг 3: total = 3 + 3 = 6
Шаг 4: total = 6 + 4 = 10
Шаг 5: total = 10 + 5 = 15
Результат: 15

Анализ сложности

Временная сложность: O(n)

  • n = количество элементов массива
  • Проходим массив один раз
  • Каждая итерация выполняет O(1) операцию

Пространственная сложность: O(1)

  • Используем только одну переменную total
  • Не зависит от размера входного массива
Читать полностью ->
Определение цикла в связном списке
2.0 Middle🔥 20💬 1

Решение: Определение цикла в связном списке

Описание проблемы

Нужно определить, содержит ли односвязный список цикл (loop). Цикл — это когда некоторый узел указывает на один из предыдущих узлов, создавая бесконечный путь.

Требуемые метрики:

  • Временная сложность: O(n)
  • Пространственная сложность: O(1)

Подход 1: Алгоритм Флойда (Черепаха и Заяц) — Оптимальный

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
Читать полностью ->
Написать автотест на вход в систему
2.0 Middle🔥 20💬 1

Решение: Автотест логина с Page Object Model

Структура проекта

tests/
  pages/
    login_page.py
    home_page.py
    base_page.py
  test_login.py
  conftest.py

1. Base Page (Базовый класс)

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

class BasePage:
    def __init__(self, driver, timeout=10):
        self.driver = driver
        self.wait = WebDriverWait(driver, timeout)
    
    def wait_for_element(self, by, locator):
        return self.wait.until(EC.presence_of_element_located((by, locator)))
    
    def wait_for_clickable(self, by, locator):
        return self.wait.until(EC.element_to_be_clickable((by, locator)))
    
    def wait_for_url(self, url):
        return self.wait.until(EC.url_contains(url))

2. Login Page

from selenium.webdriver.common.by import By
from pages.base_page import BasePage
Читать полностью ->
Написать CSS селектор
2.0 Middle🔥 20💬 1

Решение

CSS селекторы — это фундаментальный навык QA-автоматизатора при работе с Selenium, Playwright и другими фреймворками. Правильно написанный селектор — залог надёжности и поддерживаемости тестов.

1. Все строки таблицы (кроме заголовка)

#users-table tr.row

Объяснение: Селектор #users-table выбирает таблицу по ID, затем спускаемся к элементам tr с классом row. Это исключает заголовок, так как у него класс header, а не row.

Альтернативные варианты:

  • #users-table tr:not(.header) — все строки таблицы, кроме заголовка
  • table#users-table tr.row — более специфичный селектор

2. Активная строка

#users-table tr.row.active

Объяснение: Селектор ищет элемент tr, у которого одновременно присутствуют классы row и active. В нашем HTML это вторая строка данных с Jane.

Читать полностью ->
Банки с таблетками
2.2 Middle🔥 20💬 1

Решение

Описание задачи

Классическая логическая задача, которая проверяет творческое мышление и умение выбирать оптимальную стратегию при ограниченных ресурсах. Нужно использовать весы только один раз, чтобы найти одну тяжелую банку среди 20.

Ключевая идея

Вместо поиска отдельной банки используем кодирование информации через количество таблеток с каждой банки. Таким образом, одно взвешивание даст нам информацию о всех банках сразу.

Алгоритм решения

Шаг 1: Подготовка

  • Нумеруем банки от 1 до 20

Шаг 2: Взятие таблеток

  • Из банки №1 берём 1 таблетку
  • Из банки №2 берём 2 таблетки
  • Из банки №3 берём 3 таблетки
  • ...
  • Из банки №20 берём 20 таблеток

Всего возьмём: 1 + 2 + 3 + ... + 20 = 20 × 21 / 2 = 210 таблеток

Шаг 3: Взвешивание

  • Кладём все 210 таблеток на весы
  • Записываем результат в граммах

Шаг 4: Вычисление ответа

Если бы все таблетки весили 1 грамм, общий вес был бы 210 граммов.

Читать полностью ->
Проверка палиндрома
2.0 Middle🔥 20💬 1

Решение: Проверка палиндрома

Описание задачи

Требуется реализовать функцию для определения, является ли строка палиндромом (palindrome). Палиндром — это строка, которая читается одинаково в обе стороны: как слева направо, так и справа налево. Проверка палиндромов — частая задача в алгоритмическом тестировании и валидации данных, особенно при работе с пользовательским вводом и обработкой текста.

Решение на Python

def is_palindrome(s):
    """
    Проверяет, является ли строка палиндромом.
    
    Args:
        s: проверяемая строка
    
    Returns:
        True, если строка палиндром, False иначе
    """
    # Очищаем строку: удаляем пробелы и приводим к нижнему регистру
    cleaned = s.replace(' ', '').lower()
    return cleaned == cleaned[::-1]

Альтернативные подходы

1. Использование двух указателей

Читать полностью ->
Преобразование camelCase в snake_case
2.3 Middle🔥 19💬 1

Решение

Анализ задачи

Необходимо преобразовать строку из camelCase в snake_case. Это часто встречается при работе с API, где названия полей приходят в camelCase (JavaScript/JSON), а нужно преобразовать их в snake_case (Python). Критично при автоматизации тестирования REST API.

Решение

import re

def camel_to_snake(camel_case_str: str) -> str:
    """Преобразует camelCase в snake_case."""
    if not isinstance(camel_case_str, str):
        raise TypeError("Входное значение должно быть строкой")
    if not camel_case_str:
        return ""
    
    snake_case = re.sub(r"([a-z])([A-Z])", r"\1_\2", camel_case_str)
    return snake_case.lower()
Читать полностью ->
Найти единственное число
1.7 Middle🔥 19💬 1

Решение

Понимание задачи

Все числа в массиве встречаются ровно два раза, кроме одного числа, которое встречается один раз. Нужно найти это единственное число.

Оптимальный подход: XOR

Используем свойство XOR:

  • a ^ a = 0 (число XOR с самим собой дает 0)
  • a ^ 0 = a (число XOR с 0 дает само число)
  • XOR коммутативна: a ^ b ^ c = a ^ c ^ b

Проходим по массиву и XOR-им все числа. Парные числа дадут 0, а единственное число останется.

Реализация

def single_number_xor(nums: list[int]) -> int:
    """Найти единственное число, используя XOR"""
    result = 0
    for num in nums:
        result ^= num
    return result

def single_number_hash(nums: list[int]) -> int:
    """Найти единственное число, используя хеш-таблицу"""
    count = {}
    for num in nums:
        count[num] = count.get(num, 0) + 1
    
    for num, cnt in count.items():
        if cnt == 1:
            return num
    
    return 0
Читать полностью ->
Проверка скобок в выражении
1.7 Middle🔥 19💬 1

Решение

Понимание задачи

Проверить, что все скобки в выражении расставлены корректно. Для этого нужно:

  • Каждой открывающей скобке соответствует закрывающая
  • Порядок соответствия правильный (нет пересечений)
  • Поддерживать три типа скобок: (), [], {}

Оптимальный алгоритм: Stack

def is_valid_parentheses(s):
    stack = []
    mapping = {')': '(', ']': '[', '}': '{'}
    
    for char in s:
        if char in mapping:
            # Закрывающая скобка
            if not stack or stack[-1] != mapping[char]:
                return False
            stack.pop()
        elif char in mapping.values():
            # Открывающая скобка
            stack.append(char)
    
    # Stack должен быть пустой
    return len(stack) == 0

Как это работает

Пример 1: (1 + 2) * (3 + 4)

Читать полностью ->
Нахождение максимального элемента
1.8 Middle🔥 19💬 1

Решение: Нахождение максимального элемента в массиве

Описание проблемы

Нужно найти наибольший элемент в массиве, не использоваихая встроенные функции типа max(). Это фундаментальная задача, проверяющая понимание итерации, сравнения и логики управления состоянием. Рассмотрю несколько подходов с разными уровнями оптимизации.

Подход 1: Простой линейный поиск

def find_maximum(arr):
    """
    Находит максимум простой итерацией по всем элементам.
    
    Args:
        arr: List[int] - массив целых чисел
    
    Returns:
        int - максимальный элемент
    
    Raises:
        ValueError - если массив пуст
    """
    if not arr:  # Обработка пустого массива
        raise ValueError("Массив не может быть пустым")
    
    max_value = arr[0]  # Инициализируем первым элементом
    
    for i in range(1, len(arr)):  # Начинаем со второго элемента
        if arr[i] > max_value:
            max_value = arr[i]
    
    return max_value
Читать полностью ->
K-й элемент с конца списка
2.0 Middle🔥 19💬 1

Решение

Задача требует найти K-й элемент с конца в односвязном списке. Это классическая задача, которая демонстрирует работу с указателями и требует выбора между пространством и временем.

Определение структуры узла

class ListNode:
    """Класс для представления узла односвязного списка."""
    def __init__(self, value: int):
        self.value = value
        self.next = None

Решение 1: Двухпроходный алгоритм (Оптимально)

Первый проход определяет длину списка, второй проход находит нужный элемент.

Читать полностью ->
Проверка на простое число
2.3 Middle🔥 19💬 1

Решение: Проверка на простое число

Описание задачи

Требуется реализовать функцию для определения, является ли число простым (prime number). Простое число — это натуральное число, которое делится только на 1 и на само себя. Проверка простоты чисел — фундаментальная задача в программировании и криптографии, часто встречается в QA автоматизации при тестировании математических алгоритмов и валидации числовых данных.

Решение на Python

Читать полностью ->
Каждый N-й элемент
2.0 Middle🔥 18💬 1

Решение

Анализ задачи

Необходимо извлечь каждый N-й элемент из массива. Это типичная задача на работу с индексами и срезами данных, которая часто используется в автоматизации тестирования при выборке данных из логов, ответов API или выборке тестовых случаев из больших наборов.

Решение

Создам несколько вариантов решения:

def get_every_nth_element(arr: list, n: int) -> list:
    """Возвращает каждый N-й элемент из массива."""
    if n <= 0:
        raise ValueError("N должно быть положительным числом")
    if not arr:
        return []
    
    return arr[n - 1::n]
Читать полностью ->
Спиральный обход матрицы
2.3 Middle🔥 18💬 1

Решение: Спиральный обход матрицы

Это задача требует обхода матрицы по спирали: слева направо, сверху вниз, справа налево, снизу вверх, и повторения этого процесса для внутренних слоёв матрицы. Используем подход с четырьмя указателями границ.

Алгоритм решения

  1. Инициализируем четыре указателя для границ матрицы: top, bottom, left, right
  2. Проходим спирально:
    • Слева направо по верхней строке (top)
    • Сверху вниз по правому столбцу (right)
    • Справа налево по нижней строке (bottom), если есть оставшиеся строки
    • Снизу вверх по левому столбцу (left), если есть оставшиеся столбцы
  3. Сужаем границы после каждого прохода
  4. Повторяем пока не обойдём всю матрицу

Визуализация

Матрица 3x3:
1 2 3
4 5 6
7 8 9

Шаг 1 - Слева направо по top: 1, 2, 3 (top--)
Шаг 2 - Сверху вниз по right: 6, 9 (right--)
Шаг 3 - Справа налево по bottom: 8, 7 (bottom--)
Шаг 4 - Снизу вверх по left: 4, 5 (left++)

Результат: [1, 2, 3, 6, 9, 8, 7, 4, 5]
Читать полностью ->
Поиск пиковых элементов
2.0 Middle🔥 18💬 1

Решение: Поиск пиковых элементов

Пиковый элемент — это элемент, который больше всех своих соседей. На краях массива элементы имеют только одного соседа. Решение требует правильной обработки граничных случаев.

Определение пикового элемента

  • Элемент в середине массива — пиков, если больше левого И правого соседей
  • Первый элемент — пик, если больше второго (не учитываем несуществующего левого соседа)
  • Последний элемент — пик, если больше предпоследнего (не учитываем несуществующего правого соседа)
  • Массив из одного элемента — этот элемент всегда пик

Алгоритм решения (наивный)

  1. Обработираем первый элемент: если он больше второго (или массив из одного элемента) — это пик
  2. Проходим по средним элементам: проверяем каждый элемент с обоих сторон
  3. Обрабатываем последний элемент: если он больше предпоследнего — это пик
  4. Возвращаем все найденные пики

Реализация (простой подход)

Читать полностью ->
Преобразование римского в число
2.2 Middle🔥 18💬 1

Решение: Преобразование римского числа в целое число

Римская система счисления использует буквы для обозначения чисел. Ключевой момент — правило вычитания: когда меньшее значение стоит перед большим, оно вычитается.

Таблица значений

БукваЗначение
I1
V5
X10
L50
C100
D500
M1000

Алгоритм решения

  1. Проходим по каждому символу римского числа слева направо
  2. Проверяем следующий символ (если есть)
  3. Если текущее значение < следующего — вычитаем из результата
  4. Иначе — прибавляем к результату
  5. Возвращаем результат

Реализация на Python

Читать полностью ->
Поиск дубликатов в массиве
2.0 Middle🔥 18💬 1

Основные подходы к поиску дубликатов в массиве целых чисел

Задача поиска дубликатов в массиве – классическая и часто встречается на собеседованиях. Существует несколько подходов, каждый с разной эффективностью и требованиями к памяти. Основное внимание уделяется выбору алгоритма в зависимости от ограничений: можно ли использовать дополнительные структуры данных, допустима ли сортировка исходного массива, важна ли сложность по времени или памяти.

1. Использование HashSet (или словаря) – наиболее эффективный по времени подход

Этот метод использует дополнительную память для отслеживания уже встреченных элементов. Он работает за линейное время O(n) и требует O(n) дополнительной памяти (в худшем случае).

Алгоритм:

  • Проходим по массиву.
  • Для каждого элемента проверяем, присутствует он уже в HashSet (seen).
  • Если присутствует – добавляем в результат (duplicates).
  • Если нет – добавляем в seen.
Читать полностью ->
Реверс слов в предложении
2.0 Middle🔥 18💬 1

Решение

Описание задачи

Необходимо развернуть порядок слов в строке без использования встроенных коллекций (List, Array, Vector и т.д.). Это требует творческого подхода к манипулированию строками с использованием стека вызовов или встроенных строковых операций.

Подход 1: Манипулирование символами

Реализуем логику вручную, проходя по строке и выделяя слова:

def reverse_words_manual(s: str) -> str:
    result = ""
    current_word = ""
    
    for i in range(len(s) - 1, -1, -1):
        char = s[i]
        
        if char == " ":
            if current_word:
                result += current_word[::-1] + " "
                current_word = ""
        else:
            current_word += char
    
    if current_word:
        result += current_word[::-1]
    
    return result.strip()

Подход 2: Двойной реверс (для Python)

def reverse_words(s: str) -> str:
    return " ".join(word for word in s.split()[::-1])

Подход 3: На JavaScript

Читать полностью ->
Пары чисел с заданной суммой
1.7 Middle🔥 18💬 1

Решение

Задача требует найти все пары чисел в массиве, чья сумма равна целевому значению. Это фундаментальная задача, которая требует выбора оптимального подхода в зависимости от требований.

Решение 1: Хеш-таблица (Оптимальное для больших данных)

Используем HashSet для отслеживания уже посещённых элементов. Это позволяет находить все пары за один проход.

def find_pairs_hashmap(arr: list[int], target_sum: int) -> list[tuple[int, int]]:
    """
    Находит все пары чисел с заданной суммой используя хеш-таблицу.
    
    Args:
        arr: Массив целых чисел
        target_sum: Целевая сумма
    
    Returns:
        Список всех пар чисел, сумма которых равна target_sum
    
    Time Complexity: O(n)
    Space Complexity: O(n)
    """
    pairs = []
    seen = set()
    
    for num in arr:
        complement = target_sum - num
        
        if complement in seen:
            pairs.append((complement, num))
        
        seen.add(num)
    
    return pairs
Читать полностью ->
Две суммы
2.0 Middle🔥 17💬 1

Решение

Понимание задачи

Найти индексы двух чисел в массиве, сумма которых равна целевому значению. Каждый элемент используется только один раз, индексы должны отличаться.

Два подхода

1. Хеш-таблица (оптимальный)

  • Проходим по массиву один раз
  • Для каждого числа проверяем: есть ли complement = target - current_num
  • Сохраняем число и его индекс в словаре
  • Временная сложность: O(n), Память: O(n)

2. Два указателя (для отсортированного массива)

  • Левый указатель в начале, правый в конце
  • Двигаем указатели в зависимости от суммы
  • Временная сложность: O(n log n), Память: O(1)

Реализация

def two_sum_hash(nums: list[int], target: int) -> list[int]:
    """Найти индексы двух чисел, сумма которых равна target"""
    seen = {}  # {число: индекс}
    
    for i, num in enumerate(nums):
        complement = target - num
        if complement in seen:
            return [seen[complement], i]
        seen[num] = i
    
    return []  # Не найдено
Читать полностью ->
Написать тест на pytest
2.2 Middle🔥 17💬 1

Решение

Структура тестирования с pytest

pytest — современный фреймворк для автоматизации тестирования на Python с поддержкой fixtures и параметризации.

Реализация калькулятора

# calculator.py

class Calculator:
    """Класс калькулятора с базовыми операциями"""
    
    def add(self, a, b):
        return a + b
    
    def subtract(self, a, b):
        return a - b
    
    def multiply(self, a, b):
        return a * b
    
    def divide(self, a, b):
        if b == 0:
            raise ValueError("Деление на ноль невозможно")
        return a / b

Тесты на pytest

# test_calculator.py

import pytest
from calculator import Calculator

@pytest.fixture
def calculator():
    """Fixture для инициализации калькулятора"""
    return Calculator()
Читать полностью ->
Подсчет вхождений слова в текст
2.2 Middle🔥 17💬 2

Развернутый ответ на задачу о подсчете вхождений слов

В качестве QA Automation инженера с 10+ лет опыта, я подхожу к этой задаче не только с точки зрения написания рабочего кода, но и с учетом тестируемости, производительности, читаемости и потенциальных крайних случаев. Задача кажется простой, но в реальных проектах она часто усложняется требованиями к обработке разных языков, пунктуации, регистра и производительности на больших объемах данных.

Ключевые аспекты реализации

  1. Нормализация текста: Приведение к нижнему регистру для регистронезависимого подсчета.
  2. Токенизация: Разделение текста на слова. Важно корректно обработать пунктуацию и пробелы.
  3. Структура данных: Использование словаря (хэш-таблицы) для подсчета, так как операции добавления и поиска в среднем занимают O(1).
  4. Обработка крайних случаев: Пустая строка, повторяющиеся пробелы, знаки препинания, смешанные языки.

Базовая реализация на Python

Читать полностью ->
Транспонирование матрицы
2.2 Middle🔥 17💬 1

Решение задачи на транспонирование матрицы

В контексте QA Automation, задача по транспонированию матрицы является отличным примером для проверки понимания основ программирования, работы с многомерными массивами и алгоритмического мышления. Это задание часто используется на собеседованиях для оценки способности кандидата писать чистый, эффективный и корректно работающий код.

Алгоритмический подход

Для транспонирования матрицы необходимо преобразовать строки исходной матрицы в столбцы результирующей матрицы. Если исходная матрица имеет размерность m x n (m строк, n столбцов), то транспонированная матрица будет иметь размерность n x m.

Ключевые шаги алгоритма:

  1. Определить количество строк и столбцов исходной матрицы
  2. Создать новую матрицу с "перевернутыми" размерами
  3. Пройти по всем элементам исходной матрицы и присвоить result[j][i] = matrix[i][j]

Реализация на Python

Читать полностью ->
Первый неповторяющийся символ
2.3 Middle🔥 17💬 1

Решение: Первый неповторяющийся символ

Эта задача требует поиска первого символа, который встречается только один раз в строке. Решается за два прохода по строке: первый для подсчёта частоты символов, второй для поиска первого неповторяющегося.

Алгоритм решения

  1. Создаём словарь/хеш-таблицу для подсчёта частоты каждого символа
  2. Первый проход: Проходим по строке и считаем, сколько раз встречается каждый символ
  3. Второй проход: Проходим по строке заново и возвращаем первый символ с частотой 1
  4. Если таких нет: Возвращаем -1 или None (в зависимости от требований)

Реализация решения

Читать полностью ->
Среднее арифметическое
2.0 Middle🔥 17💬 1

Решение

Анализ задачи

Нужно вычислить среднее арифметическое элементов массива. Формула:

Average = (сумма всех элементов) / (количество элементов)

Задача проста на первый взгляд, но требует учитывать граничные случаи.

Решение 1: Простое вычисление

def average(arr):
    if not arr:
        return 0  # Или raise ValueError
    total = 0
    for num in arr:
        total += num
    return total / len(arr)

Пояснение:

  • Сначала проверяем что массив не пуст
  • Суммируем все элементы
  • Делим на количество элементов

Пример:

[10, 20, 30, 40, 50]
сумма = 150
количество = 5
среднее = 150 / 5 = 30.0

Решение 2: С использованием встроенных функций

def average(arr):
    if not arr:
        return 0
    return sum(arr) / len(arr)

Более читаемо и эффективно в Python.

Решение 3: С обработкой ошибок

Читать полностью ->
Выбор сортировки
1.8 Middle🔥 17💬 1

Решение: Selection Sort (Сортировка выбором)

Понимание алгоритма

Selection Sort работает в два этапа:

  1. Найти минимальный элемент в неотсортированной части массива
  2. Поменять его с первым элементом неотсортированной части
  3. Сдвинуть границу отсортированной части на одну позицию

Решение 1: Классическая реализация

def selection_sort(arr: list[int]) -> list[int]:
    arr_copy = arr.copy()
    
    for i in range(len(arr_copy)):
        # Найти минимальный элемент в оставшейся части
        min_idx = i
        for j in range(i + 1, len(arr_copy)):
            if arr_copy[j] < arr_copy[min_idx]:
                min_idx = j
        
        # Поменять элементы местами
        arr_copy[i], arr_copy[min_idx] = arr_copy[min_idx], arr_copy[i]
    
    return arr_copy

Time Complexity: O(n^2) Space Complexity: O(1) если сортировать in-place

Решение 2: In-place сортировка (оптимально)

Читать полностью ->
Тестирование формы регистрации
2.0 Middle🔥 17💬 1

Решение

Анализ требований

Форма регистрации содержит 4 основных элемента:

  1. Email - почтовый адрес (валидация формата)
  2. Пароль - минимум 8 символов, должен содержать цифру и спецсимвол
  3. Подтверждение пароля - должно совпадать с паролем
  4. Чекбокс согласия - должен быть отмечен
  5. Кнопка регистрации - активируется при всех корректных данных

1. Тест-кейсы на граничные значения

Email

Читать полностью ->
Генерация всех правильных скобочных последовательностей
2.0 Middle🔥 17💬 1

Решение

Описание проблемы

Генерация всех правильных скобочных последовательностей (valid parentheses combinations) — это фундаментальная задача на использование рекурсии и backtracking. Правильная последовательность должна удовлетворять условиям:

  • Количество открывающих скобок = количеству закрывающих
  • На любой префиксной позиции количество открывающих скобок >= закрывающих

Подход решения

Используем рекурсивный backtracking алгоритм:

  1. Отслеживаем количество оставшихся открывающих и закрывающих скобок
  2. На каждом уровне проверяем условия:
    • Если открывающих > 0, можем добавить открывающую скобку
    • Если закрывающих > открывающих в текущей последовательности, можем добавить закрывающую
  3. Когда обе переменные = 0, добавляем результат в ответ

Реализация на Python

Читать полностью ->
Слияние отсортированных списков
1.7 Middle🔥 17💬 1

Решение

Задача требует объединения двух отсортированных списков в один отсортированный результат. Это классическая задача, которая часто встречается на собеседованиях и тесно связана с алгоритмом merge из сортировки MergeSort.

Подход с двумя указателями (Two-Pointer Technique)

Оптимальное решение использует технику двух указателей с временной сложностью O(n + m), где n и m — длины списков. Идея проста: проходим оба списка одновременно, сравниваем элементы и добавляем меньший в результат.

Читать полностью ->
Сортировка пузырьком
2.0 Middle🔥 17💬 1

Решение: Сортировка пузырьком

Описание задачи

Требуется реализовать алгоритм сортировки пузырьком (bubble sort) для массива целых чисел без использования встроенных методов сортировки. Сортировка пузырьком — это классический алгоритм сортировки, который многократно проходит по массиву, сравнивает соседние элементы и обменивает их местами, если они находятся в неправильном порядке. Хотя в реальной практике этот алгоритм считается неэффективным (O(n²)), он является отличным инструментом обучения и часто встречается в тестировании алгоритмов, обучении программированию и интервью.

Решение на Python

Читать полностью ->
Разворот массива
1.7 Middle🔥 17💬 1

Решение: Разворот массива

Описание задачи

Требуется реализовать метод, который принимает массив целых чисел и возвращает его в полностью обратном порядке. Первый элемент становится последним, второй — предпоследним, и так далее. Данная операция часто называется разворотом массива (array reversal) и является фундаментальным алгоритмом в программировании.

Решение на Python

def reverse_array(arr):
    """
    Разворачивает массив целых чисел в обратном порядке.
    
    Args:
        arr: список целых чисел
    
    Returns:
        список целых чисел в обратном порядке
    """
    return arr[::-1]

Альтернативные подходы

1. Встроенный метод reverse()

def reverse_array(arr):
    # Изменяет массив на месте и возвращает None,
    # поэтому нужно вернуть копию
    arr_copy = arr.copy()
    arr_copy.reverse()
    return arr_copy

2. Использование двух указателей

Читать полностью ->
Проверка на подпоследовательность
2.0 Middle🔥 16💬 1

Решение: Проверка на подпоследовательность

Подпоследовательность — это последовательность, которая может быть получена из другой последовательности путём удаления некоторых элементов без изменения порядка оставшихся элементов. Решается через двухточечный проход по строкам.

Определение подпоследовательности

  • Подпоследовательность НЕ требует смежности элементов
  • Порядок символов ДОЛЖЕН сохраняться
  • Пустая строка всегда подпоследовательность любой строки

Примеры:

  • "abc" — подпоследовательность "ahbgdc" (a_b_c)
  • "axc" — НЕ подпоследовательность "ahbgdc" (нет x)
  • "" — подпоследовательность любой строки

Алгоритм (двухточечный подход)

Читать полностью ->
Валидация числа
1.8 Middle🔥 16💬 1

Анализ задачи и подход к решению

Задача на валидацию строки как числа (целого или с плавающей точкой) классическая и часто встречается на собеседованиях. Она проверяет понимание конечных автоматов (Finite State Machine, FSM), умение работать с граничными случаями и писать чистый, тестируемый код.

Основная сложность — корректно обработать все возможные форматы числа без использования регулярных выражений (если это явно не разрешено) и встроенных функций преобразования строк в числа (например, parseInt, parseFloat, Number()), так как они могут некорректно обрабатывать некоторые случаи (например, parseInt("12.5") вернет 12, игнорируя .5).

Ключевые аспекты валидации

Читать полностью ->
Наибольший общий делитель
2.0 Middle🔥 16💬 2

Развернутый ответ на вопрос о реализации функции для поиска НОД

Наибольший общий делитель (НОД) двух целых чисел — это наибольшее положительное целое число, которое делит оба исходных числа без остатка. Алгоритм поиска НОД является классической задачей, часто используемой в программировании для проверки понимания базовых алгоритмов и математических концепций.

Основные алгоритмы для вычисления НОД

Существует несколько эффективных алгоритмов для решения этой задачи:

1. Метод перебора (для понимания логики, но неэффективный)

Простейший способ — проверка всех чисел от меньшего из двух чисел до 1, но это крайне неэффективно для больших значений.

def gcd_naive(a: int, b: int) -> int:
    smaller = min(a, b)
    for divisor in range(smaller, 0, -1):
        if a % divisor == 0 and b % divisor == 0:
            return divisor
    return 1
Читать полностью ->
SQL запрос с JOIN
2.0 Middle🔥 16💬 1

Решение

Понимание задачи

Необходимо связать три таблицы через JOIN для получения информации о пользователях, их заказах и продуктах в одном результирующем наборе данных.

SQL Запрос

SELECT 
    u.name AS user_name,
    p.name AS product_name,
    o.amount
FROM orders o
JOIN users u ON o.user_id = u.id
JOIN products p ON o.product_id = p.id
ORDER BY u.name, p.name;

Разбор запроса

Структура JOIN:

  1. Начинаем с таблицы orders — это центральная таблица, которая содержит внешние ключи на users и products
  2. JOIN users: связываем заказы с пользователями через o.user_id = u.id
  3. JOIN products: связываем заказы с продуктами через o.product_id = p.id

Выбор INNER JOIN:

  • INNER JOIN возвращает только записи, которые есть во всех трёх таблицах
  • Это правильный выбор, так как каждый заказ должен иметь пользователя и продукт
  • Если бы были NULL значения, они не выводились бы
Читать полностью ->
SQL запрос для поиска дубликатов
2.0 Middle🔥 16💬 1

Решение

Поиск дубликатов в базе данных — частая задача при тестировании, валидации данных и подготовке тест-кейсов. Правильно написанный SQL запрос позволяет быстро выявить проблемы с уникальностью данных.

Основной запрос

SELECT email, COUNT(*) as count
FROM employees
GROUP BY email
HAVING COUNT(*) > 1
ORDER BY count DESC;

Объяснение:

  • SELECT email, COUNT(*) — выбираем email и считаем количество повторений
  • FROM employees — из таблицы employees
  • GROUP BY email — группируем по email адресу
  • HAVING COUNT(*) > 1 — фильтруем группы с дубликатами
  • ORDER BY count DESC — сортируем по количеству повторений

Расширенный запрос

SELECT e.*
FROM employees e
WHERE e.email IN (
  SELECT email
  FROM employees
  GROUP BY email
  HAVING COUNT(*) > 1
)
ORDER BY e.email;

Показывает все записи с дублирующимися email адресами.

С оконной функцией

Читать полностью ->
Отсутствующее число в файле
2.0 Middle🔥 16💬 1

Решение

Анализ проблемы

Это классическая задача интервью на понимание ограничений памяти и оптимизации:

Дано:

  • 4 миллиарда 32-битных целых чисел в файле
  • Диапазон 0 до 2^32-1 (около 4.3 млрд значений)
  • Одного числа не хватает
  • Ограничена оперативная память

Решение 1: Побитовое XOR

def findMissing(filename):
    result = 0
    
    # XOR всех чисел 0..2^32-1
    for i in range(2**32):
        result ^= i
    
    # XOR с числами в файле
    with open(filename, 'rb') as f:
        while True:
            chunk = f.read(4)
            if not chunk:
                break
            num = int.from_bytes(chunk, byteorder='little')
            result ^= num
    
    return result

Почему работает: a ^ a = 0, поэтому парные элементы исчезают, остаётся непарный.

Решение 2: Математическая сумма

Читать полностью ->
Факториал числа
1.7 Middle🔥 16💬 1

Решение факториала

Рекурсивный подход

def factorial_recursive(n: int) -> int: if n < 0: raise ValueError("Факториал только для неотрицательных чисел") if n == 0 or n == 1: return 1 return n * factorial_recursive(n - 1)

Итеративный подход

def factorial_iterative(n: int) -> int: if n < 0: raise ValueError("Факториал только для неотрицательных чисел") result = 1 for i in range(2, n + 1): result *= i return result

Встроенная функция

import math result = math.factorial(5) # 120

Примеры

  • 0! = 1
  • 1! = 1
  • 5! = 120
  • 10! = 3628800

Анализ сложности

ПодходВремяПамятьПрименение
РекурсивныйO(n)O(n)Элегантно, ограничен
ИтеративныйO(n)O(1)Производство, надежно
ВстроеннаяO(n)O(1)Оптимально
Читать полностью ->
Сумма без оператора плюс
2.3 Middle🔥 16💬 1

Решение

Задача требует сложить два числа без использования оператора + или арифметических операторов. Это задача, которая демонстрирует понимание битовых операций и принципов работы с числами на низком уровне.

Решение 1: Битовые операции (XOR + AND)

Основной подход — использовать XOR для суммирования битов и AND с левым сдвигом для переноса.

Читать полностью ->
Второй по величине элемент
2.0 Middle🔥 16💬 1

Решение

Задача требует найти вторую по величине зарплату из таблицы Employees. Это классическая SQL задача с несколькими подходами разной сложности и эффективности.

Решение 1: DISTINCT + ORDER BY + LIMIT (Рекомендуемое)

Простое и понятное решение, которое работает в подавляющем большинстве случаев.

SELECT MAX(salary) AS second_largest
FROM Employees
WHERE salary < (SELECT MAX(salary) FROM Employees);

Решение 2: DISTINCT с OFFSET (Альтернативное)

Использует DISTINCT для удаления дубликатов зарплат, затем сортирует и берёт вторую.

SELECT DISTINCT salary
FROM Employees
ORDER BY salary DESC
LIMIT 1 OFFSET 1;

Решение 3: Подзапрос с MAX (Оптимальное)

Находит максимальную зарплату среди всех, которые меньше чем глобальный максимум.

SELECT MAX(salary) AS second_largest_salary
FROM Employees
WHERE salary < (SELECT MAX(salary) FROM Employees);

Решение 4: Window Functions (Модерный подход)

Читать полностью ->
Общие элементы двух массивов
2.0 Middle🔥 16💬 1

Решение: Общие элементы двух массивов

Описание задачи

Требуется реализовать метод для поиска пересечения двух массивов (intersection of arrays). Необходимо найти все элементы, которые присутствуют в обоих массивах одновременно, и вернуть их. Эта задача часто встречается в тестировании обработки коллекций данных, сравнении наборов данных, анализе пересечений и работе с множествами. Решение требует выбора оптимального алгоритма в зависимости от размера массивов и наличия дубликатов.

Решение на Python

Читать полностью ->
Проверка анаграмм
1.7 Middle🔥 16💬 1

Решение: Проверка анаграмм

Описание задачи

Требуется реализовать функцию для определения, являются ли две строки анаграммами (anagrams) друг друга. Анаграмма — это слово или фраза, составленная из тех же букв, что и исходное слово, но в другом порядке. При проверке необходимо игнорировать регистр букв, пробелы и знаки препинания. Эта задача часто встречается в тестировании обработки текстовых данных, валидации пользовательского ввода и работе со строками в автоматизированном тестировании.

Решение на Python

Читать полностью ->
Проверка валидного email
2.0 Middle🔥 15💬 1

Решение: Валидация email адреса

Решение 1: Регулярное выражение (Практичное)

import re

def is_valid_email_regex(email: str) -> bool:
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return re.match(pattern, email) is not None

Плюсы:

  • Простое и понятное
  • Работает для большинства случаев
  • Практично для реальных приложений

Минусы:

  • Regex не идеален для email по RFC
  • Может пропустить или отклонить валидные адреса

Решение 2: RFC 5322 (Более строгое)

import re
Читать полностью ->
Реализация стека
1.8 Middle🔥 15💬 1

Решение

Описание структуры данных

Стек (Stack) — это абстрактный тип данных, реализующий принцип LIFO (Last In, First Out). Последний добавленный элемент — первый удаляемый.

Подход 1: Реализация на Python с использованием списка

Читать полностью ->
Уникальные символы в строке
2.0 Middle🔥 15💬 1

Решение

Задача требует определить, являются ли все символы в строке уникальными, БЕЗ использования дополнительных структур данных. Это требует творческого подхода к решению задачи в условиях строгих ограничений.

Решение 1: Без дополнительных структур — Сортировка

Если буквально не использовать дополнительные структуры, можно отсортировать символы и проверить соседние элементы. Это использует встроенные функции, но не создаёт новые структуры данных явно.

Читать полностью ->