在C中搜索算法和复杂性的一个小任务。我只是想确保我正确。
我有从1到n + 1的n个自然数,从小到大排序,我需要找到丢失的数字。 例如:1 2 3 5 6 7 8 9 10 11 - ans:4
最快和最简单的答案是做一个循环,并用它后面的数字检查每个数字。在最坏的情况下,复杂性是O(n)。
我想也许我错过了一些东西,我可以使用二进制搜索找到它。在这个简单的例子中,有人能想到更高效的算法吗? 喜欢O(log(n))还是什么?
答案 0 :(得分:1)
显然有两个答案:
如果您的问题纯粹是理论上的问题,特别是对于大型n
,您可以执行类似二进制搜索的操作,并检查最后两个边界之间的中间位置是否实际为(upper-lower)/2
。
然而,如果这是一个实际问题,对于现代系统执行用C
编写并由n << 10000
的现代高度优化编译器编译的程序,我假设线性搜索方法更快,更快,因为它可以很容易地进行矢量化。事实上,现代CPU有指令要采取例如每个
等等,它非常巧妙地适用于CPU和内存控制器预取线性内存的事实,因此,以对数下降步长跳转可能会产生巨大的性能影响。
所以:对于大型n
,线性搜索不切实际,请选择二元搜索方法;对于那些有问题的n
,请进行线性搜索。如果您不仅具有SIMD功能而且还具有多个内核,那么您将需要分解问题。如果您的问题实际上不是正好1 缺失的数字,您可能希望使用完全不同的方法......整个O(n)
业务通常更像是一个纯粹用于理论构造的基准,除非差异非常大,否则很少是在实际实现中选择特定算法的唯一理由。
答案 1 :(得分:0)
对于基于比较的算法,在最坏的情况下,您无法胜过Lg(N)
比较。这只是因为答案是1
和N
之间的数字,并且需要Lg(N)
位信息来表示这样的数字。 (并且比较会给你一点。)
除非答案的分布非常偏离,否则你的平均成绩不会比Lg(N)
好得多。
现在我不知道基于非比较的方法如何利用序列的有序性,并且比O(N)
做得更好。