完全披露这是一个家庭作业问题,因此,我不会要求具体的解决方案,只是一些问题的一般答案。问题的内容如下:
给定一个必须实现Comparable接口的T类型的排序数组, 编写一个Java泛型方法,用于查找数组中的特定元素 并返回它,如果找不到则返回null。请注意您的算法 必须在日志库3时间运行更糟糕的情况,一个日志库2(二进制搜索)解决方案 将不会获得任何信用
还有一个额外的规定,算法必须是迭代的,而不是递归的。
1)所以我的第一个问题是,如何确定算法在日志库3中运行而不是日志库2?这两者只有一个常数因子不同,所以即使我分析算法的结构,我怎么知道我是在Log3(n)时间运行,还是只运行在(~0.63)(Log2(n))时间?它甚至重要吗?
2)我认为二进制搜索或多或少是用于搜索排序数组的标准快速算法,而不是二进制和线性搜索,还有哪些其他搜索算法可供我们寻找灵感?
3)是否有一些我缺少的东西,一些规定可以让搜索阵列的速度比标准的二进制搜索更快?
非常感谢任何帮助,对不起,如果这个问题相当具体,但我认为它的某些部分通常是适用的。
答案 0 :(得分:2)
是的,O(log(n))并不关心log是base 2还是base 3。
现在假设任务是使用不超过一定数量的比较。我们可以证明,在最坏的情况下,在不超过log 3 (N)比较的情况下解决它是不可能的。对于初学者来说,如果数组有三个元素,那么在一次比较之后就不可能找到元素或报告它丢失了。同样,对于九元素阵列,两次比较显然是不够的。人们可以使用鸽子原则和一些关心来证明它对大N来说也是不可能的,尽管我承认我在几分钟内没有做出短证明。 我证明我尝试大N的证据就是这个(虽然细节变得乏味)。如果所有数组元素都是不同的并且与我们搜索的数据不同,我们在询问K个问题后只获得K位信息,因此可以区分数组中不超过2个 K 段X可能在哪里。然后,存在一定长度的段(例如,3个元素),并且在其中,我们没有比较但仍然可以等于X的元素。将其更改为X,我们获得反例数组。
答案 1 :(得分:1)
二进制搜索的主要好处是简单;给定一个包含端点if(!is_page_template( 'single.php' ))
和x
的子数组,您可以进行一次比较和一次中点计算,以确定下一个子数组(y
或[x,(x+y)/2]
。
使用三元搜索,您需要进行两个比较和两个中点计算,以确定要搜索[(x+y)/2, y]
,[x, (x+y)/3]
或[(x+y)/3, 2*(x+y)/3]
中的哪一个下一个。你可以更快地缩小范围,但代价是更多的工作。
渐近地,它们都是[2*(x+y)/3, y]
。二进制搜索获胜因为它很简单,但也因为您认为访问下一个键并不比用于确定它的比较更昂贵。对于在存储器中连续存储的数组,这最终是正确的,因为最终子数组适合主存储器,然后完全适合每个连续级别的高速缓存。 (也就是说,数组具有良好的空间局部性)。
对于不存储在数组中的数据 - 例如,在树中 - 获取下一个节点的成本可能远远超过确定哪个所需的比较成本要获取的节点。在这种情况下,您希望在每次获取时尽可能多地将有用数据加载到内存中。在这种情况下,三元树可能不比二叉树好得多,但是类似于B-tree,其中每个内部节点的大小(确定节点中可以存储多少个键)是调整到本地缓存的大小,可以大大减少实际运行时间,即使它仍然像O(lg(n))一样二进制搜索。
答案 2 :(得分:-2)
我相信如果你做的事情比仅仅在每次迭代中将集合减半,那么你可以比简单的二进制搜索更好。
您可以选择 pivot ,方法是将输入视为单调函数而不是一系列值。
布伦特算法使用这种方法,可以让你更快收敛。
请参阅https://en.wikipedia.org/wiki/Brent%27s_method
如果是我的任务,我的解决方案就是基于此。