这是一个面试问题。
给定一个整数数组,找到数组中出现偶数频率的单个整数值。所有整数都是正数。所有其他数字出现奇数频率。数组中的最大数字可以是INT_MAX。
例如,[2,8,6,2]应返回2.
如果您可以找到更好的解决方案,例如O(1)空间和O(n)时间,则可以修改原始数组。
我知道如何通过哈希表(遍历和计数freq)来解决它。它是O(n)时间和空间。
是否有可能通过O(1)空间或更好的时间来解决它?
答案 0 :(得分:6)
鉴于这是一个面试问题,答案是:O(1)空间是可以实现的“非常大的值1”:
这个空间很大,但与输入数组的大小无关,所以O(1)空间。对于非常大的数据集(比如小值范围,但是阵列长度很大),这甚至可能是一个实际有效的解决方案。
答案 1 :(得分:4)
如果允许对原始数组进行排序,我相信您可以在O(n lg U)时间和O(lg U)空间中执行此操作,其中U是数组的最大元素。这个想法如下 - 使用in-place MSD radix sort,在O(n lg U)时间和O(lg U)空间中对数组进行排序。然后,遍历数组。由于所有相等的值都是连续的,因此您可以计算每个值出现的次数。一旦找到偶数次出现的值,就可以输出答案。第二次扫描需要O(n)时间和O(1)空间。
如果我们假设U是固定常数,则给出O(n) - 时间,O(1) - 空间算法。如果你不假设这一点,那么内存使用率仍然优于O(n)算法,只要lg U = O(n),在大多数机器上都应该如此。此外,空间使用仅与最大元素对数一样大,这意味着实际空间使用非常好。例如,在64位计算机上,我们只需要足够的空间来容纳64个递归调用。这比预先分配一个巨大的数组要好得多。此外,这意味着该算法是一个弱多项式时间算法,作为U的函数。
也就是说,这会重新排列原始数组,从而破坏性地修改输入。从某种意义上说,它是作弊的,因为它将数组本身用于O(n)存储空间。
希望这有帮助!
答案 2 :(得分:1)
扫描列表,保持两组,“偶数”设置和“奇数”设置。如果之前没有看到过某个元素(即如果它们都没有被设置过),请将它放在“奇数”集中。如果元素在一个集合中,则将其移动到另一个集合。最后,'Even'集合中应该只有一个项目。这可能不会很快,但对于大型列表,内存使用应该是合理的。
答案 3 :(得分:0)
- 创建一个包含整数的哈希表。称之为is_odd或其他东西。由于您可能需要查看大小为INT_MAX的数组,因此只需将其设置为大小为INT_MAX的数组即可。初始化为0。
- 遍历整个阵列。你必须这样做。没有办法击败O(n)。
for each number:
if it's not in the hash table, mark its spot in the table as 1.
if it is in the hash table then:
if its value is '1', make it '2'
if its value is '2', make it '1'.
现在你必须遍历哈希表。拉出唯一的条目,以“2”作为值。
时间: 你遍历数组一次和哈希表一次,所以O(n)。
空间: 只是一个大小为INT_MAX的数组。或者,如果您知道阵列的范围,则可以将内存使用限制在此范围内。
编辑:我刚看到你已经有了这个方法。对不起!
答案 4 :(得分:-2)
我想我们不正确地阅读了这个任务。它要求我们“找到数组中出现偶数频率的单个整数值”。因此,假设只有一个偶数元素,解决方案是:
public static void main(String[] args) {
int[] array = { 2, 1, 2, 4, 4 };
int count = 0;
for (int i : array) {
count^=i;
}
System.out.println(count); // Prints 1
}