← Назад к вопросам
Удаление дубликатов из массива
2.0 Middle🔥 111 комментариев
#Теория тестирования
Условие
Напишите функцию, которая удаляет дубликаты из массива, сохраняя исходный порядок элементов.
Пример
Вход: [1, 2, 2, 3, 4, 4, 5] Выход: [1, 2, 3, 4, 5]
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Решение
Анализ задачи
Задача требует удалить дубликаты из массива, сохраняя исходный порядок элементов. Это важное уточнение — существует несколько подходов в зависимости от требований:
- Простой подход — использовать хеш-множество (Set)
- Подход с двумя указателями — для отсортированного массива
- Встроенные функции — если язык их предоставляет
Мы рассмотрим все три, так как на собеседовании ценится понимание trade-offs.
Решение 1: Использование Set (Python)
def removeDuplicates(arr: list[int]) -> list[int]:
"""
Удаляет дубликаты, сохраняя порядок через dict (3.7+).
Сложность: O(n) время, O(n) память
"""
# dict.fromkeys() сохраняет порядок в Python 3.7+
return list(dict.fromkeys(arr))
Этот подход:
- Сохраняет порядок в Python 3.7+ (dict упорядочен)
- Линейная сложность O(n)
- Простота кода
Решение 2: Явное использование множества
def removeDuplicates(arr: list[int]) -> list[int]:
"""
Удаляет дубликаты с явной проверкой через set.
"""
seen = set()
result = []
for num in arr:
if num not in seen:
seen.add(num)
result.append(num)
return result
Преимущества:
- Явная логика — понятна на собеседовании
- Работает в любой версии Python
- Полный контроль над процессом
- Сложность: O(n) время, O(n) память
Решение 3: Java реализация
public class Solution {
public static List<Integer> removeDuplicates(int[] arr) {
// Используем LinkedHashSet для сохранения порядка
Set<Integer> seen = new LinkedHashSet<>(Arrays.asList(
Arrays.stream(arr).boxed().toArray(Integer[]::new)
));
return new ArrayList<>(seen);
}
}
Альтернатива (более явная):
public class Solution {
public static List<Integer> removeDuplicates(int[] arr) {
Set<Integer> seen = new LinkedHashSet<>();
List<Integer> result = new ArrayList<>();
for (int num : arr) {
if (seen.add(num)) { // add() возвращает false если элемент уже был
result.add(num);
}
}
return result;
}
}
Решение 4: JavaScript/TypeScript
function removeDuplicates(arr) {
// Используем Set для уникальности
// Set в JavaScript сохраняет порядок вставки
return [...new Set(arr)];
}
// С типизацией (TypeScript)
function removeDuplicates(arr: number[]): number[] {
return [...new Set(arr)];
}
Решение 5: Для отсортированного массива (2 указателя)
Если массив отсортирован, можно использовать две указатели:
def removeDuplicates(arr: list[int]) -> list[int]:
"""
Удаляет дубликаты в отсортированном массиве на месте.
Возвращает новый массив (или можно изменять исходный).
Сложность: O(n) время, O(1) дополнительная память
"""
if not arr:
return arr
write_pos = 0
for read_pos in range(1, len(arr)):
if arr[read_pos] != arr[write_pos]:
write_pos += 1
arr[write_pos] = arr[read_pos]
return arr[:write_pos + 1]
Сравнение подходов
| Подход | Время | Память | Сортировка | Преимущества |
|---|---|---|---|---|
| Set/dict | O(n) | O(n) | Нет | Простой, работает с неотсортированными данными |
| Два указателя | O(n) | O(1) | Требуется | Минимум памяти, в-плейс |
| Встроенные функции | O(n) | O(n) | Зависит | Самый короткий код |
Тестовые случаи
# Основной пример
assert removeDuplicates([1, 2, 2, 3, 4, 4, 5]) == [1, 2, 3, 4, 5]
# Граничные случаи
assert removeDuplicates([]) == [] # Пустой массив
assert removeDuplicates([1]) == [1] # Один элемент
assert removeDuplicates([1, 1, 1, 1]) == [1] # Все дубликаты
assert removeDuplicates([1, 2, 3, 4, 5]) == [1, 2, 3, 4, 5] # Нет дубликатов
# Сохранение порядка
assert removeDuplicates([5, 2, 5, 3, 2, 1]) == [5, 2, 3, 1] # Порядок первого появления
Рекомендация для QA
При тестировании:
- Пустой массив — должен вернуть пустой массив
- Нет дубликатов — массив не должен измениться
- Все дубликаты — должна остаться одна копия
- Смешанные данные — проверить сохранение порядка первого появления
- Большие массивы — проверить производительность
- Отрицательные числа — если применимо
Выбор подхода зависит от контекста — для собеседования рекомендую Решение 2 (явное использование set): оно показывает понимание алгоритма и работает везде.