java找出不重复的数_关于Java:在整数数组中查找第一个非重复数

我有一个考试题:

Given an integer array find the first number which is not repeating in array using O(N) time complexity and O(1) space complexity.

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

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

也许它是指非重复的连续数字,在这种情况下,您只需要将数字与上一个数字进行比较即可?这样看起来似乎很琐碎,但这只是一个简单的想法。

我不认为仅仅是因为您使用固定大小的Collection,这意味着空间复杂度是1 ...

是否可以假设数组已排序?

@AbishekManoharan固定大小集合的空间复杂度为1

您提供的声明有问题。 O(N)时间和O(1)空间无法解决该任务。

如果定义了输入的最大大小,那么渐近复杂性将变得毫无意义,因为您始终可以根据限制分配足够的内存,并且始终可以进行足够的操作以将时间和空间复杂性都定为常数。如果忽略最大输入,则不可能使用固定大小的容器。

@nafas不,如果集合大小为N,则显然不是O(1)大小复杂度,而是O(N)。

现在,假设我不是一个整数数组,而是一个带有A-Z字母大写的字符串,我必须先找到不重复的字符,然后才能将一个固定大小的char映射为整数,然后遍历该数组并填充该映射。最后,我可以遍历地图以查找角色。在那种情况下,空间复杂度为O(1)。因为map的大小是恒定的,所以为什么我不能分配一个100万大小的数组并在自定义hashmap中使用它,并且在这里具有O(1)复杂性。

@anonymous O(1)应该表示我们对于任何给定的输入都有一个恒定的空间。在您的情况下,您需要一百万个尺寸为一百万个,而200万个尺寸为200万个。因此是O(N)空间复杂度。同样,为每个输入迭代地图意味着您的时间复杂度也高于O(N)。

请发布确切的问题陈述。有时他们会欺骗您,这比您想的要简单。

是的,请提供原始问题陈述。这样我们将更容易回答。

@AdamStelmaszczyk为什么不这样呢,例如气泡排序的空间复杂度是O(1),无论集合的大小如何。

数字是否都在1 .. arraySize范围内?如果是这样,通过巧妙地重用数组本身,可以(令人惊讶地)找到O(n)时间和O(1)空间中的所有重复项(不是* non- * duplicates):请参见cafs和我的回答。

@nafas,因为气泡排序是就地完成的,除了已被排序的集合已占用的空间之外,不使用其他任何空间。

* @ AlexanderRevo气泡排序使用恒定数量的额外空间(如果您没记错的话,它仍然具有该临时空间)。因此,只要创建新空间是一个常数,那么空间复杂度为O(1)

显而易见的解决方案是对数组进行排序,然后在排序后的数组中查找相邻的重复项。排序通常为O(n lg n),或更糟糕的是,但是您可以使用基数排序对O(n)中的整数进行排序。 (这是否会比传统算法快,这是另一个问题,但这是O(1)。)

埃森哲面试问题的可能重复部分-查找数组中唯一未配对的元素

看起来与此类似(实际上有一个答案):stackoverflow.com/questions/7370978/

您不需要次数。因此,对于性能而言,单例的分布很重要。 1 Mio中相等分布的随机int(32位)。整数会导致很多单例,因此您只需要遍历整个数组一次,两次甚至三遍。如果几乎所有值都出现两次以上,则将重复项存储在HashMap中可能会有所帮助。然后,您可以快速查找它们。如果每个值在图中仅是1或2倍,其中大多数是2倍,则可能是病理输入。

在给定的整数数组中查找第一个非重复数

更新:找到了一个更好的解决方案。

我认为我们可以使用诸如HashMap的其他数据结构以O(n)时间复杂度解决它。遍历数组,然后将元素作为键,并将元素在数组中的索引位置作为映射中的值。如果键已经存在,则可以删除键值对,也可以将值设置为-1。

一旦遍历整个数组,我们就可以从哈希图中获取keySet(),然后找到具有最低值(忽略-1)的键。

所以这将是

时间复杂度:O(N)

空间复杂度:O(N)

旧的解决方案:我们可以通过创建另一个数组来解决此问题,该数组是通过对给定数组进行排序获得的。这将花费O(nlogn)时间。

那么我们可以遍历给定输入数组中的每个元素,尝试查找该元素并与已排序数组中的下一个元素进行比较,如果重复执行给定数组中的下一个元素,如果不重复,那么我们发现第一个非重复给定输入整数数组中的元素。

时间复杂度:O(nlogn)

空间复杂度:O(n)

附注:很抱歉,您还没有阅读所有评论,James Kanze已经在评论中提供了此解决方案,感谢他。

如果除一个元素(不重复)外,所有元素正好有两个条目(或2的倍数),则可以使用XOR运算符。

例:

int x=arr[0];

for(i=1;i<1000;i++)

x^=a[i];

printf("Non-repeating: %d",x);

与自身进行XOR运算的任何数字均为0。因此,如果任何数字出现两次,则在整个XOR结果中将为0,因此在x中仅保留非重复数字。

注意:如果您有100万个数字,则用于存储XOR结果的变量必须足够大。

-1,对不起。这个答案是正确的,但是它不能回答OP的问题。第一句话等于"如果这是一个不同的问题,则可以使用XOR运算符"。

这似乎不能解决问题,什么是数组[1,2,3,1]?那怎么回答2?

@nafas:请仔细阅读我的回答的第一行。我刚刚提供了这个想法,根据问题的要求,该想法的实际实施取决于解决者自己!

@skrtbhtngr对不起朋友,鉴于它可以正常工作

我不明白这一点。即使除一个元素外,所有元素都恰好有两个条目,它也会执行二进制XOR运算并正确赋值?您能详细说明一下吗?

假设数组为[11,26,35,26,11],则对所有元素进行XOR运算将得到答案:35。这是XOR操作的一个属性。如果XOR操作的操作数相等,则其返回0,因此仅保留非重复元素。

知道了..谢谢...但是您的代码无法在数组中输入0的情况下工作...对吗?

对@AbishekManoharan。这只是一个示例代码片段。它有很大的空间可以进行输入验证和优化。

@AbishekManoharan:为什么您认为这段代码不会为零工作? (我的意思是,不要误会我的意思-该代码根本上是错误的,因为它不支持nafas给出的示例-但其所有问题都与零支持无关。)

@ruakh,您是对的,只要给出"如果除一个元素外,所有元素的正好有两个(或为2的倍数)条目,它将对零起作用"

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

我相信解决问题的技巧是:

max size of array would be 1million

由于:

O(1) space means that the memory required by the algorithm is constant

那么给定常数1M,空间复杂度将自动变为O(1)。注意。尽管1M确实是一个很大的数字,但它仍然是一个常数。因此我们只需要关注时间复杂度。

使用LinkedHashMap,我们可以使用O(1)添加新元素,并使用O(1)检索元素,因此更新条目也将占用O(1)。它也是preserves the order。因此,我们可以找到最早的条目

那么问题将通过两个步骤变得简单:

建立LinkedHashMap-> O(n)

找出计数为0的最早数字-> O(n)

上述每个步骤都需要O(n),因此总体time complexity为O(2n) = O(n)。

这样,您可以使任何算法在恒定空间中执行。我怀疑这种"把戏"是否在这里。没有参加考试。

@JensG如果有上限,则可以使空间复杂度保持不变

您回答了错误的观点。关键是,考试中很可能没有技巧问题。即使有一个,也没有这么愚蠢的一个。

@JensG我会想到这个问题的目的是了解空间复杂性的真正含义是什么。所以您只需要知道1M仍然是一个常数

这是O(n)大小复杂度。恒定空间复杂度的真正含义是算法空间需求不取决于输入大小。如果您的算法使用4个字节来处理100个元素,则应该使用相同的4个字节来处理1000亿个元素,这样才能说具有恒定的空间复杂度。

@AlexanderRevo对于给定的问题将始终使用1M *(无论1M Entires的字节映射是多少)。因为假设大小不会超过1M

@nafas ...复杂度是针对算法确定的..不是针对问题...仅仅因为此问题的上限为1M,并不意味着您的算法具有o(1)复杂度...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值