如何设计一种有效的最小上界搜索算法

时间:2009-02-27 14:17:07

标签: algorithm search

假设你有一组具有已知下界和未知上界的数字,即0,1,2,3 ...... 78,其中78是未知数。假设目前数字之间没有间隙。有一个耗时的函数test()可以测试数字是否在集合中。

什么是一种有效的方式(需要少量test()次来电)来查找集合中的最高数字?

如果您具有上限为75 +/- 25?

的附加知识,该怎么办?

如果集合中的数字之间存在随机间隙,即0,1,3,4,7 ...... 78,该怎么办?

7 个答案:

答案 0 :(得分:3)

对于“无间隙案”:

  • 我认为这是一个固定的数字大小,例如一个32位的int
  • 我们希望找到x test(x) == truetest(x+1) == false,对吧?

你基本上在最低已知“未设置”(例如最大32位int)和最高已知“in set”之间进行二进制切换(启动通过测试每次范围中的中间值并相应地调整边界,使用已知的下限。这将提供O(log N)解决方案(就 test() 的调用次数而言),其中X潜力的大小设置,而不是实际设置。对于小型集合来说,这比仅仅尝试1,2,3 ...更慢,但对于大型集合来说要快得多。

如果可能存在差距,所有这一切都会失败,此时我认为没有任何可行的解决方案,除了“以绝对最高可能的数字开始,直到test(x) == true为止,这是最高的数”。就我所见,任何其他策略都会失败或更昂贵。

答案 1 :(得分:1)

你最好的选择是简单地运行O(n)复杂度的集合,这不错。

考虑到集合没有排序(毕竟它是一个集合,这是给定的),每个isInSet(n)操作也需要O(n),带你到{{1对于整个操作,如果你在某些地方为 prodding 选择任何算法......

一个更好的解决方案,如果该控件位于您的控件中,则只需保留该组的最大值,并在每次插入时更新它。对于所有情况,这将是O(n^2)

答案 2 :(得分:1)

  1. Step设为1
  2. Upper设为Lower + Step
  3. 如果test(Upper)为真,则将Lower设为Upper,将Step乘以2,然后转到第2点
  4. 此时您知道Lower在您的集合中,而Upper则不在。{1}}。您现在可以在LowerUpper之间进行二进制搜索,以查找限制。
  5. 这看起来像O(log n * O(测试))复杂性。

    如果您知道Upper介于50和100之间,请在这两个值之间进行二元搜索。

    如果你有随机间隙并且你知道上限是100最大值我怀疑你做得比从那里开始并逐个测试每个数字要好,直到test()在你的集合中找到一个值。 / p>

    如果你有随机差距并且知道上限,那么你永远不会确定你找到了上限。

答案 3 :(得分:0)

也许你应该遍历它?这将是O(n)复杂。我认为没有其他办法可以做到这一点。

答案 4 :(得分:0)

你知道预先设定的尺寸吗?

实际上,我猜你可能没有 - 否则第一个问题就是微不足道了。

如果你知道这套装置有多大,那会有所帮助。

  1. 猜测最高值
  2. 测试 - 如果然后增加一些数值
  3. 如果不是那么减少价值
  4. 一旦你有最大值的上限和下限,二进制搜索直到你找到它(达到要求的精度)。
  5. 对于你没有这种能力的差距 - 你甚至无法判断你何时找到了最大的元素。 (除非你知道最大间隙大小)

答案 5 :(得分:0)

如果没有间隙,那么你最好用二分搜索。

如果我们使用第二个假设,即顶部是75 +/- 25,那么低端是50而高端是100,我们的第一个测试用例是75.如果它存在,则低端是75和高端是100,我们的测试用例是87.那应该得到O(ln N)的结果(这里N将是50)。

如果我们不能假设可能的上限,我们只需要对它可能是什么进行有根据的猜测。如果找不到值,它就变成了高端。如果找到它,它就是低端,我们将它翻倍以找到高端。

如果存在差距,我能看到的唯一方法是进行线性搜索 - 但即使这样,你也需要一种了解何时到达终点的方法,而不仅仅是一个很大的差距。

答案 6 :(得分:0)

如果您的套装恰好是素数集,请在找到最大号码时告诉我。我相信我们可以解决问题。 ;)

但是说真的,我猜你知道这个集确实具有最大价值。或者,你把它砍成32位整数。

一些建议:

1)想想你可能会加速test(x)== false结果的每一种情况。然后你可以继续下一个。如果您花费在所有弹射情况上的时间远远少于完成全部测试,那么您将领先一步。 2)你能从每次测试中获得任何信息吗?例如,test(x)== false是否意味着test(x + 5679)== false?