在数组中查找不重复三倍的元素?
阅读后这个有趣的问题让我想起了我曾经遇到过的一个棘手的面试问题,但我从未给出令人满意的答案:
给定一个由 n 个 32 位无符号整数组成的数组,其中每个元素(除了一个)都重复三倍。在 O(n) 时间内,使用尽可能少的辅助空间,找到数组中未出现 3 次倍数的元素。
举个例子,给定这个数组:
1 1 2 2 2 3 3 3 3 3 3
给定数组,我们将输出 1
3 2 1 3 2 1 2 3 1 4 4 4 4
我们将输出 4。
通过使用哈希表计算每个元素的频率,可以在 O(n) 时间和 O(n) 空间中轻松解决这个问题,尽管我强烈怀疑,因为问题陈述特别提到数组包含 32 位无符号整数,所以有更好的解决方案(我猜测 O(1) 空间)。
有谁对如何解决这个问题有任何想法?
After reading this interesting question I was reminded of a tricky interview question I had once that I never satisfactorily answered:
You are given an array of n 32-bit unsigned integers where each element (except one) is repeated a multiple of three times. In O(n) time and using as little auxiliary space as possible, find the element of the array that does not appear a multiple of three times.
As an example, given this array:
1 1 2 2 2 3 3 3 3 3 3
We would output 1, while given the array
3 2 1 3 2 1 2 3 1 4 4 4 4
We would output 4.
This can easily be solved in O(n) time and O(n) space by using a hash table to count the frequencies of each element, though I strongly suspect that because the problem statement specifically mentioned that the array contains 32-bit unsigned integers that there is a much better solution (I'm guessing O(1) space).
Does anyone have any ideas on how to solve this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
它可以在 O(n) 时间和 O(1) 空间内完成。
以下是如何在 C# 中使用常量空间来实现这一点。我使用“异或除了三态位”的想法。对于每个设置位,“异或”运算会递增相应的三态值。
最终输出将是其二进制表示形式在最终值中 1 或 2 的位置有 1 的数字。
It can be done in O(n) time and O(1) space.
Here is how you can do it with constant space in C#. I'm using the idea of "xor except with 3-state bits". For every set bit, the "xor" operation increments the corresponding 3-state value.
The final output will be the number whose binary representation has 1s in places that are either 1 or 2 in the final value.
在恒定空间中执行此操作的明显解决方案是使用就地算法对其进行排序,然后在数组上扫描一次。
遗憾的是,这通常需要 O(n log n) 时间和 O(1) 空间。
但由于条目的密钥长度有限(32 位),您可以使用基数排序作为排序算法(存在就地基数排序,它们不稳定,但这并不重要)。在那里你有 O(n) 时间和 O(1) 空间。
编辑:顺便说一句,您可以使用这种方法来查找所有出现次数不是 3 倍数的数字,以防万一您允许多个数字可以具有此属性。
The obvious solution to do it in constant space is to sort it using an in place algorithm, and then scan once over the array.
Sadly this requires usually O(n log n) time and O(1) space.
But as the entries have a limited key length (32 bit) you can use as sort algorithm radix sort (there exist in place radix sort, they are not stable, but that doesnt matter here). There you have O(n) time and O(1) space.
EDIT: Btw you could use this approach to find also ALL numbers that appear not a multiple of 3 times, in case you would allow that more than one number could have this property.
您正在寻找重复次数非零 (mod 3) 的项目。我想我会递归地做到这一点:
甚至不需要尝试优化基本算法之外的东西(例如,不用担心每次计数只存储两位),这似乎做得很好。我已经添加了代码来生成相当大的测试用例(例如,1500 多个项目)并打印出它正在创建的地图的大小。在任何给定时间,它创建的地图中似乎最多有大约 50 个项目(即,它一次只使用两个地图,我见过的最大的项目约为 25 个)。从技术上讲,就目前情况而言,我相信目前的时间复杂度类似于 O(N log N),但如果您切换到基于哈希的容器,我相信您会期望 O(N)。
You're looking for an item with a rep-count that's non-zero (mod 3). I think I'd do it recursively:
Without even trying to optimize things beyond the basic algorithm (e.g., not worrying about storing only two bits per count), this seems to do pretty well. I've included code to generate a reasonably large test case (e.g., 1500+ items) and print out the sizes of the maps it's creating. At any given time, it seems to have a maximum of around 50 items in the maps it creates (i.e., it only uses two maps at a time, and the largest I've seen is around 25 items). Technically, as it stands I believe this is currently something like O(N log N), but if you switched to a hash-based container, I believe you'd expect O(N).
计算每个位的总数(0-31,假设 int 是 32 位)并将每个位的计数存储在数组中。完成后,迭代生成的位计数数组,并检查哪个位位置出现的次数不是模 3 次,并根据这些位构造最终的数字。完整的代码如下(也适用于负数):
Count the total number of each bit (0–31, assuming int is 32-bits) and store the count of each bit in an array. When finished, iterate over the resulting array of bits count and check which bit position occurs not a modulo 3 times and construct your final number based upon those bits. Complete code is below (works properly for the negative numbers too):