使用分而治之的方法检测数组中的重复项

时间:2012-04-12 16:40:23

标签: algorithm

我在考试时得到了以下问题,似乎可能无法实现。有什么我想念的吗?

给定一个n个对象的数组,只能进行相等性比较,并且对数组中的值范围一无所知,给出一个分而治之的解决方案,用于检测数组中是否存在任何重复项。这必须是O(nlogn)解决方案。

我们可以安全地假设,由于问题的性质,解决方案可能与数据结构或基数排序无关,所以可以就地进行吗?

若然,怎么样?

6 个答案:

答案 0 :(得分:6)

如果您无法订购商品,则无法检查O(nlogn)中的重复项,如果只能比较相等,则无法订购。

事实上,你不能确定没有重复项,除非你比较每一对,并且有n(n-1)/2个这样的对。

答案 1 :(得分:1)

如何使用hashset。将每个项目添加到集合中。然后检查尺寸。但是,这不是分而治之的。


比较相等的结果会告诉你被比较的两个对象中哪一个是“更大”吗?

如果你可以创建一组对象的总排序,我想你可以使用一个inplace divide和conq排序算法,但添加一些检测重复的附加逻辑。 (将< = check转换为<和== check)

答案 2 :(得分:0)

由于它是O(nlogn),基本上你可以对数组进行排序并找到重复项。既然你想使用分而治之,我建议使用quicksort。

答案 3 :(得分:0)

你在NlogN时间内做到这一点的唯一方法就是“作弊”。

在.NET和Java中,接口的任何实现,如.NET的IEquatable(仅公开Equals()方法),也是基础对象。 .NET和Java中的对象具有散列函数(在.NET中它是GetHashCode();在Java中它是hashCode())。因此,无论接口限制您使用哪种方法,您始终都可以访问将产生数值的散列函数。

这将允许您散列每个对象并比较散列的相对大小。这反过来允许您通过哈希对数组进行排序,然后以线性时间扫描它以检测重复项。您可以就地执行此操作,或者您可以通过将每个项目插入到键入哈希值的红黑树,哈希表或字典中来保持原始数组的完整性(所有这些都具有logN或更好的访问时间以及logN或更好的插入次)。

正如评论中所述,任何这些方法都可以并行化为多个线程,从而实现“分而治之”的要求;排序可以使用并行MergeSort完成,同时根据您在环境中可以访问的对象,您可以使用线程安全的“并发”集合,从而允许您将数组拆分为插入到集合中的子数组。多线程。如果您将每个线程的子数组重叠一个元素,则可以并行化扫描已排序的列表,从而防止重复对中的一个项目位于一个子数组中,另一个项目位于下一个子数组中。

答案 4 :(得分:0)

也许还有另一种方法可以考虑分析?

同意,O(N ^ 2)中的最坏情况。但最好的情况是O(1)。

纯粹看待只有equal的事实,并且值的范围是未知的,那么可以公平地说只有一种方法来获得N ^ 2,那就是所有的值是不同的,还是不平等的?

同样,只有一种方法可以保证在1次测试中找到重复,即所有值都相等的时候。

在找到相同的对之前,有很多方法无法比较所有对象。如果有N / 2对,N / 3三元组,N / 4四元组,N / sqrt(N)组sqrt(N)重复等,在找到一对之前必须比较多少,即重复?< / p>

我认为这就像是'通过从袜子中抽出一双不同数量的相同袜子来找到一双袜子,两套或多套相同的袜子'。袜子的主人通过购买未知数量的相同袜子来补充抽奖,并在袜子上有一个洞时扔掉袜子。我们不知道袜子穿的速度有多快,或者老板买袜子的速度有多快。

平均上,我们不会期望 比N ^ 2更好吗?

答案 5 :(得分:-1)

您可以使用改进的quicksort解决此问题。如果不是比较>,只需将其替换为相等运算符即可。修改后的快速排序会将项目分组在一起。

然后您要做的就是寻找条纹来寻找骗子。

看看这个例子。

https://repl.it/@fernandozamoraj/DearJollySynergy