Поиск первого неповторяющегося числа в целочисленном массиве
Я получил этот вопрос для экзамена:
учитывая целочисленный массив, найдите первое число, которое не повторяется в массиве, используя 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
. поэтому мы можем найти самую раннюю запись
тогда проблема станет простой в два шага:
- создайте LinkedHashMap --> O (n)
- найдите самое раннее число, количество которого равно 0 --> O (n)
каждый из вышеуказанных шагов требует O (n) таким образом в целом time complexity
is O(2n) = O(n)
.