在整数数组中找到第一个不重复的数字

11

我在考试中遇到了这个问题:

给定一个整数数组,使用O(N)时间复杂度和O(1)空间复杂度找到第一个不重复的数字。

我想不出任何解决方案。我知道可以遍历整个数组并维护一个linkedhashmap,它将存储数组元素和它出现的次数,然后最后要在hashmap中搜索以找到那个数字。空间复杂度大于O(1),但我想不出其他解决方案。

我还仔细阅读了问题,并说数组的最大大小将为100万。我认为,如果我们可以创建一个自定义哈希映射,它将利用一个固定大小的1百万大小的数组,那么可以在O(1)空间复杂度下完成此操作,因为在这种情况下所需的存储量将是恒定的,但不确定我是否正确。请告诉我是否有其他解决方案。


3
也许它指的是非重复连续数字,这种情况下,你只需要将一个数字与前一个数字进行比较。这似乎太简单了,但这只是一个快速的想法。 - tibtof
5
使用固定大小的集合并不意味着空间复杂度为1,这并不是一个正确的想法。 - Codebender
1
@AbishekManoharan,固定大小的集合具有空间复杂度为1。 - nafas
2
@nafas 不,如果集合大小为N,显然它的大小复杂度不是O(1),而是O(N)。 - Adam Stelmaszczyk
5
请发布确切的问题陈述。有时他们会试图欺骗你,但实际上问题比你想象的简单。 - NathanOliver
显示剩余14条评论
4个回答

1
假设除了一个元素是非重复的之外,所有元素都有两个(或整数倍于2个)条目,您可以使用XOR运算符。
例子:
int x=arr[0];
for(i=1;i<1000;i++)
  x^=a[i];
printf("Non-repeating: %d",x);

任何数字与自身进行异或运算的结果都是0。因此,如果任何数字出现两次,它们在整体异或结果中将变为0,只有不重复的数字会留在x中。
注意:如果您有100万个数字,则存储异或结果的变量必须足够大。

1
-1,抱歉。这个答案是正确的,但它没有回答到提问者的问题。第一句话的意思是,“如果这是一个不同的问题,你可以使用异或运算符。” - ruakh
6
似乎这并不能解决问题,如果数组是[1,2,3,1],那么怎么回答2呢? - nafas
@nafas:请仔细阅读我的回答的第一行。我刚刚提供了这个想法,根据问题的要求实际实现这个想法取决于求解者自己! - skrtbhtngr
我不理解这个。即使除了一个元素外,所有元素都恰好有两个条目,它也会执行二进制异或并搞乱值,对吗?你能详细说明一下吗? - Codebender
2
假设数组为[11,26,35,26,11],则对所有元素进行异或操作将会得到答案:35。这是异或运算的一个性质。如果它的操作数相等,则异或运算返回0,因此只保留不重复的元素。 - skrtbhtngr
显示剩余5条评论

1
在给定的整数数组中查找第一个不重复的数字。
更新:找到了更好的解决方案。我认为我们可以使用额外的数据结构,如HashMap,在O(n)时间复杂度内解决它。遍历数组,并将元素作为键和元素在数组中的索引位置作为值放入映射中。如果键已经存在,则可以删除键值对或将值设置为-1。一旦遍历整个数组,那么我们就可以从hashmap获取keySet(),然后找到具有最低值的键(忽略-1)。所以这将是 时间复杂度:O(N) 空间复杂度:O(N)
旧解决方案:我们可以通过创建另一个数组来解决这个问题,该数组是通过对给定数组进行排序获得的。这将花费O(nlogn)时间。然后,我们可以遍历给定输入数组中的每个元素,尝试找到元素并将其与排序后的数组中的下一个元素进行比较,如果重复则继续下一个元素,如果不重复,则在给定的输入数组中找到了第一个不重复的元素。
时间复杂度:O(nlogn)空间复杂度:O(n)
附言:很抱歉,没有阅读所有评论,James Kanze已经在评论中提供了此解决方案,归功于他。

0

我使用 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

-4

我认为解决这个问题的诀窍是:

数组的最大大小将会是一百万

因为:

O(1)空间意味着算法所需的内存是恒定的

因此,给定常数1M,空间复杂度将自动变为O(1)。注意:即使它是一个非常大的数字,1M仍然是一个常数。因此,我们只需要关注时间复杂度。

使用LinkedHashMap,我们可以添加一个新元素并检索具有O(1)的元素,因此更新条目也将花费O(1)。它还保留顺序。因此,我们可以找到最早的条目

然后问题就变得简单了,分为两步:

  1. 建立LinkedHashMap --> O(n)
  2. 查找计数为0的最早数字 --> O(n)

上述每个步骤都需要O(n),因此总体时间复杂度O(2n) = O(n)


1
这样你就可以让任何算法在恒定的空间中执行。我怀疑这个“技巧”是否符合预期。不适用于考试任务。 - JensG
2
你回复了错误的观点。关键是考试中很可能没有什么诡计问题。即使有一个,也不会是如此愚蠢的问题。 - JensG
@JensG 我本来以为这个问题的目的是为了理解空间复杂度的真正含义。所以你需要知道的是1M仍然是一个常数。 - nafas
1
这是O(n)的大小复杂度。常数空间复杂度的真正含义是算法的空间需求不取决于输入大小。如果您的算法使用4个字节来处理100个元素,那么它在处理1000亿个元素时应该使用相同的4个字节,以便被称为具有常数空间复杂度。 - Alexander Revo
3
算法的复杂度是由算法本身决定的,而不是由问题本身决定的。即使这个问题的上限是1M,也不能说明你的算法具有o(1)的复杂度。请注意,我已经尽力让翻译保持原意并通俗易懂,没有添加任何解释或其他内容。 - Codebender
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接