Найти в массиве неповторяющиеся числа

Дан массив:

const arr = [1,2,3,4,1,2];

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

getUniqueNums(arr)  // [3,4]

Примеры:

[1,2,3,4,1,2] --> [3,4]
[2,56,2,46,3,3] --> [56,46]
[2,16,2,6,3,3,5,4,4] --> [16,6,5]
[2] --> [2]
[2,3,3,2] --> []

Теория по задаче

Задача относится к классу задач на “частоты” (сколько раз встречается каждое значение). Правильная формулировка: необходимо вернуть те элементы массива, которые имеют частоту 1.

Шаг 1. Построение частотного словаря

Частотный словарь — это структура вида “значение → количество”. На практике для JavaScript удобны две формы: Map и обычный объект (словарь).

Пошаговая иллюстрация для [1, 2, 3, 4, 1, 2]:

Вход: [1, 2, 3, 4, 1, 2]

Подсчёт:
- встретилось 1 -> count(1) = 1
- встретилось 2 -> count(2) = 1
- встретилось 3 -> count(3) = 1
- встретилось 4 -> count(4) = 1
- встретилось 1 -> count(1) = 2
- встретилось 2 -> count(2) = 2

Итог:
1 -> 2
2 -> 2
3 -> 1
4 -> 1

Шаг 2. Отбор значений с частотой 1

После подсчёта выполняется проход по исходному массиву и проверка: если count(value) === 1, элемент добавляется в результат. Это удобно делать через filter(), потому что он возвращает новый массив из тех элементов, которые прошли проверку.

Эквивалентная запись без filter() (то же самое, но “вручную”):

function getUniqueNums(nums) {
  const counts = new Map();
  for (const n of nums) counts.set(n, (counts.get(n) ?? 0) + 1);

  const result = [];
  for (const n of nums) {
    if (counts.get(n) === 1) result.push(n);
  }
  return result;
}
Два прохода по массиву (подсчёт, затем отбор) — нормальная и часто оптимальная схема: сначала “собираются факты” (частоты), затем применяется правило отбора.

Сложность и сравнение подходов

Обозначения:

  • n — длина массива.
  • k — количество различных значений в массиве.

Таблица сравнения:

ПодходИдеяВремяПамятьПорядок как в исходном
Map + подсчёт + filterЧастоты, затем === 1O(n)O(k)Да
Object + подсчёт + filterЧастоты в объектеO(n)O(k)Да
indexOf + lastIndexOfПервый индекс = последнийO(n²)O(1)Да

Практический вывод:

  • Если массив может быть большим, обычно выбирается вариант с Map (или объектом при гарантии “только числа”).
  • Вариант с indexOf/lastIndexOf подходит как учебный и для небольших массивов.

Кратко: неповторяющиеся элементы — это элементы с частотой 1; наиболее устойчивое решение строится через подсчёт частот (обычно Map) и последующую фильтрацию исходного массива, что даёт линейную сложность и сохраняет порядок.