Как реализовать проверку последовательных чисел в массиве
Что проверяют
Умеете ли вы превратить расплывчатое условие в точное требование и затем закрыть его тестами. Интервьюер почти наверняка спросит: «А что ваша функция вернёт для [1, 1, 3]?»
Как отвечать
Сначала уточнения. Должна ли последовательность идти в исходном порядке ([3, 4, 5]), или достаточно, чтобы числа её образовывали после перестановки ([5, 3, 4])? Как быть с пустым массивом, дубликатами и убывающим порядком?
Решения под каждую трактовку:
- в исходном порядке:
all(b - a == 1 for a, b in itertools.pairwise(arr)), один проход, O(n), без дополнительной памяти.pairwiseпоявился в Python 3.10, в старых версиях то же делают черезzip(arr, arr[1:]); - после перестановки через сортировку:
s = sorted(arr)и та же проверка соседей, O(n log n). Именноsorted, а неarr.sort(): метод меняет список вызывающего кода; - после перестановки за O(n): числа образуют ряд, если все они различны и
max(arr) - min(arr) == len(arr) - 1. Различность проверяетlen(set(arr)) == len(arr), память O(n).
Дальше выпишите тест-кейсы, для QA это главное:
- пустой и из одного элемента: результат нужно зафиксировать в требованиях;
- дубликаты:
[1, 2, 2, 3]и[1, 1, 3]; - пропуск:
[1, 2, 4]; - отрицательные и ноль:
[-1, 0, 1]; - убывание:
[3, 2, 1], ответ зависит от трактовки; - нечисловые данные:
None, строки,1.5.
Где спотыкаются
Сортируют входной список на месте. Функция проверки меняет данные вызывающего кода, и соседний тест, который переиспользует тот же список, начинает падать непредсказуемо.
В решении через минимум и максимум забывают про дубликаты: [1, 1, 3] проходит условие, потому что 3 - 1 равно len - 1, хотя это не ряд.
Не уточняют трактовку и молча выбирают одну. Для тестировщика неоднозначное требование это дефект спецификации, о котором нужно сказать вслух.