【发布时间】:2010-10-15 21:37:30
【问题描述】:
我正在考虑排序,然后进行二进制搜索。这是最好的方法吗?
【问题讨论】:
我正在考虑排序,然后进行二进制搜索。这是最好的方法吗?
【问题讨论】:
我提倡在这种情况下使用哈希:您将拥有与两个数组的共同大小成正比的时间。
由于大多数主要语言在其标准库中都提供哈希表,因此我几乎不需要向您展示如何实现此类解决方案。
【讨论】:
遍历每一个并使用哈希表来存储计数。键是整数的值,值是出现次数。
【讨论】:
这取决于。如果一组比另一组小很多,或者由于某些其他原因,您希望交集非常稀疏,那么二进制搜索可能是合理的。否则,一次通过这两个步骤可能是最简单的。如果一个中的当前元素小于另一个,则前进到该数组中的下一项。当/如果你得到相等的元素,你把它作为输出发送,然后前进到两个数组中的下一个项目。 (当然,这假设您已经对两者进行了排序)。
这是一个 O(N+M) 操作,其中 N 是一个数组的大小,而 M 是另一个数组的大小。使用二分搜索,你会得到 O(N lg2 M) ,如果一个数组比另一个数组小很多,复杂度可能会更低,但如果它们是大小差不多。
根据您的需要/想要什么,尝试仅计算出现次数的版本可能会导致相当严重的问题:如果一个数组中单个项目多次出现,它们仍会将其视为该项目的两次出现,表示实际上并不存在的交叉点。您可以防止这种情况发生,但这样做会使这项工作变得不那么简单——您将一个数组中的项目插入到哈希表中,但始终将计数设置为 1。完成后,通过将计数设置为 2 来处理第二个数组当且仅当该项目已存在于表中。
【讨论】:
定义“最佳”。
如果你想快速完成,你可以通过遍历每个数组并为每个唯一元素保持计数来完成 O(n)。如何计算唯一元素的详细信息取决于数组中可能存在的事物的字母表,例如,它是稀疏的还是密集的?
注意,数组的数量是 O(n),但长度为 m 的数组是 O(nm)。
【讨论】:
最好的方法可能是散列所有值并记录出现次数,在检查数组i 时剔除所有未出现的i 次,其中i = {1, 2, ..., n}。不幸的是,没有确定性算法可以让您获得少于O(n*m) 的运行时间,因为如果不检查所有数组中的所有值(如果它们未排序),就不可能做到这一点。
更快的算法需要具有可接受的概率水平(蒙特卡洛),或者依赖列表的某些已知条件来仅检查元素的子集(即您只关心在所有@中出现的元素987654325@ 之前的列表在考虑 ith 列表时,但在未排序的列表中搜索元素并非易事。
【讨论】: