Поиск первого неповторяющегося числа в целочисленном массиве

Я получил этот вопрос для экзамена:

учитывая целочисленный массив, найдите первое число, которое не повторяется в массиве, используя O(N) временную сложность и O (1) пространственную сложность.

Я не мог придумать никакого решения. Я знаю, что могу перебирать массив и поддерживать linkedhashmap, который будет хранить как элемент массива, так и количество раз, когда он появляется, а затем в конце я должен искать hashmap, чтобы найти это число. Сложность пространства больше O (1) но я не мог придумать другого решения.

Я также внимательно прочитал проблему, и сказал, что максимальный размер массива будет 1million. Я думаю, что если мы сможем создать пользовательский hashmap, который будет использовать массив фиксированного размера размером 1 миллион, то это может быть достигнуто в сложности пространства O(1), поскольку в этом случае требуемое хранилище будет постоянным, но не уверен, что я прав. Пожалуйста, дайте мне знать, если есть какое-либо другое решение.

4 ответов


Если есть ровно две (или кратные 2) записи для всех элементов, кроме одного элемента, который будет неповторяющимся, вы можете использовать оператор XOR.

пример:

int x=arr[0];
for(i=1;i<1000;i++)
  x^=a[i];
printf("Non-repeating: %d",x);

любое число XORed с собой равно 0. Таким образом, если какое-либо число появляется дважды, оно будет 0 в общем результате XOR, оставляя только неповторяющееся число в x.

Примечание: Если у вас есть 1 миллион чисел, переменная для хранения результата XOR должна быть достаточно большой.


чтобы найти первое неповторяющееся число в заданном целочисленном массиве

UPDATE: найдено лучшее решение. Я думаю, мы можем решить это в O(n) сложность времени с использованием дополнительной структуры данных, такой как HashMap. Выполните итерацию по массиву и поместите элемент как ключ, а позицию индекса элемента в массив как значение на карте. если ключ уже существует, можно либо удалить пару ключ-значение, либо просто установить значение -1. Как только весь массив будет пройден, мы сможем получить keySet () из hashmap, а затем найти ключ, который имеет наименьшее значение(игнорировать -1). так это будет Временная Сложность: O(N) Сложность Пространства: O (N)

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

сложность времени: O (nlogn)
сложность пространства: O (n)

P. S: извините, не прочитал все комментарии, Джеймс канце уже предоставил это решение в комментариях, кредиты ему.


Я сделал это с помощью PowerShell

[int[]]$arr = @(6,2,1,2,6,1,7)

$Collection = New-Object 'System.Collections.Generic.list[System.Object]'
$props=[ordered]@{"Index"=9999;"Value"=9999;"Numcount"=9999}
$record = New-Object -TypeName psobject -Property $props
$Collection.Add($record) #This record is added to do a Contains operation 
#for future items to be added in the $collection object

for($i =0;$i -lt $arr.Length;$i++)
{
if($i -eq 0)
{
    $props=[ordered]@{"Index"=$i;"Value"=$arr[$i];"Numcount"=1}
    $record = New-Object -TypeName psobject -Property $props
    $Collection.Add($record)
}


elseif($Collection.value.Contains($arr[$i]))
{

    $count = ($Collection | ?{$_.Value -eq $arr[$i]} | select -First `
1).Numcount
    ($Collection | ?{$_.Value -eq $arr[$i]} | select -First 1).Numcount = `
$count+1
}
else
{
    $props=[ordered]@{"Index"=$i;"Value"=$arr[$i];"Numcount"= 1}
    $record = New-Object -TypeName psobject -Property $props
    $Collection.Add($record)
}

}
Write-Output "The first non repeating number in the array is listed below"
$Collection | Sort-Object Numcount -Descending | ?{$_.Numcount -eq 1} | 
Select -First 1

OUTPUT:-
The first non repeating number in the array is listed below
Index Value Numcount
----- ----- --------
6     7        1

Я считаю, что трюк, чтобы решить эту проблему :

максимальный размер массива будет 1million

С :

O(1) пробел означает, что память, требуемая алгоритмом, равна постоянный

тогда сложность пространства автоматически станет O (1) с учетом константы 1M. Примечание. 1M по-прежнему является постоянным числом, хотя его действительно большое число. таким образом, нам нужно только сосредоточиться на времени сложность.

С помощью LinkedHashMap мы можем добавить новый элемент O(1) и получить элемент с O(1) таким образом, обновление записи также займет O(1). это тоже preserves the order. поэтому мы можем найти самую раннюю запись

тогда проблема станет простой в два шага:

  1. создайте LinkedHashMap --> O (n)
  2. найдите самое раннее число, количество которого равно 0 --> O (n)

каждый из вышеуказанных шагов требует O (n) таким образом в целом time complexity is O(2n) = O(n).