Java 在一百万个元素的数组中找到唯一唯一的元素

Java 在一百万个元素的数组中找到唯一唯一的元素,java,arrays,Java,Arrays,我在最近的一次采访中被问到这个问题 您将获得一个包含一百万个元素的数组。除一个元素外,所有元素都是重复的。我的任务是找到唯一的元素 var arr = [3, 4, 3, 2, 2, 6, 7, 2, 3........] 我的方法是在for循环中遍历整个数组,然后创建一个map,索引为数组中的number,值为数组中出现的数字的频率。然后再次循环遍历我们的映射并返回值为1的索引 我说我的方法需要时间复杂性。面试官告诉我要在不到O(n)复杂度的情况下优化它。我说我们不能,因为我们必须用一百万个

我在最近的一次采访中被问到这个问题

您将获得一个包含一百万个元素的数组。除一个元素外,所有元素都是重复的。我的任务是找到唯一的元素

var arr = [3, 4, 3, 2, 2, 6, 7, 2, 3........]
我的方法是在
for
循环中遍历整个数组,然后创建一个
map
,索引为数组中的
number
,值为数组中出现的数字的
频率。然后再次循环遍历我们的映射并返回值为1的索引

我说我的方法需要时间复杂性。面试官告诉我要在不到
O(n)
复杂度的情况下优化它。我说我们不能,因为我们必须用一百万个元素遍历整个数组

最后,他似乎不满意,转而问下一个问题

我知道在阵列中遍历百万个元素是很昂贵的,但是我们如何在不对整个阵列进行线性扫描的情况下找到唯一的元素呢


PS:数组未排序。

假设数组未排序,则无法排序。每个值与下一个值都是互斥的,因此不能从任何其他值推断出任何值

如果它是一个有序的值数组,那么这是另一回事,完全取决于使用的顺序


我同意,最简单的方法是使用另一个容器并存储值的频率。

我确信,如果您没有任何附加信息(如元素被排序并限制为特定值),那么不遍历整个数组就无法解决此问题,因此,问题的最小时间复杂度为
O(n)
。但是,如果每个元素在数组中出现偶数次(这似乎是问题的最常见变体),您可以使用基于异或的解决方案将内存复杂性降低到
O(1)
,如果您感兴趣的话:

int unique(int[] array)
{
    int unpaired = array[0];
    for(int i = 1; i < array.length; i++)
        unpaired = unpaired ^ array[i];
    return unpaired;
}
int唯一(int[]数组)
{
int unpaired=数组[0];
for(int i=1;i

基本上,每个XORed元素都会与另一个元素相消,因此您的结果是唯一一个没有相消的元素。

事实上,由于数组中的元素数是固定的,因此您可以做得比您建议的好得多

通过“创建一个
map
,索引作为数组中的数字,值作为数组中出现的数字的频率”,您可以创建一个2^32个位置的映射(假设数组有32位整数),然后您必须通过该映射找到第一个值为1的位置。这意味着您正在使用一个较大的辅助空间,在最坏的情况下,您正在执行10^6+2^32操作(100万用于创建地图,2^32用于查找元素)

不用这样做,您可以使用一些
n*log(n)
算法对数组进行排序,然后在排序后的数组中搜索元素,因为在您的例子中,
n=10^6

例如,使用合并排序,您将使用更小的辅助空间(只是一个10^6整数的数组),并执行(10^6)*log(10^6)+10^6操作来排序,然后查找元素,该元素大约为21*10^6(比10^6+2^32小很多倍)


PS:对数组进行排序将搜索成本从二次型降低到线性型,因为对于排序后的数组,我们只需访问相邻位置,以检查当前位置是否唯一。

您的方法似乎很好。这可能是因为他在寻找一个边缘情况,其中数组的大小是均匀的,这意味着要么没有不匹配的元素,要么有两个或两个以上的元素。他只是问错了方向。

关于阵列,我们还知道什么吗?分类了吗?我们知道数组中有哪些唯一值吗?您当前正在花2n时间遍历数组的每个元素,然后遍历映射的每个键,并且可以通过在注意到重复时从映射中删除键来避免第二个循环,但是
O(2n)
仍然是
O(n)
@AndrewRueckert-它没有排序。数组中的所有数字都是按随机顺序重复的,但只有一个数字不会重复。你确定他们说的是O(n)时间复杂度,而不是O(n)空间复杂度吗?你知道被复制的元素有多少个副本吗?@user2357112-他们说的是时间复杂性,而不是空间复杂性。重复可能会发生任意次数,您必须查看所有n个元素(最坏的情况是,可能会有您可以扣除其他因素的情况)。你最后看一眼可能会发现你现在的候选人是一个复制品。面试官可能对你的解释和测试不满意。