假设你有一组具有已知下界和未知上界的数字,即0,1,2,3 ...... 78,其中78是未知数。假设目前数字之间没有间隙。有一个耗时的函数test()
可以测试数字是否在集合中。
什么是一种有效的方式(需要少量test()
次来电)来查找集合中的最高数字?
如果您具有上限为75 +/- 25?
的附加知识,该怎么办?如果集合中的数字之间存在随机间隙,即0,1,3,4,7 ...... 78,该怎么办?
答案 0 :(得分:3)
对于“无间隙案”:
test(x) == true
,test(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)
Step
设为1 Upper
设为Lower + Step
test(Upper)
为真,则将Lower
设为Upper
,将Step
乘以2,然后转到第2点Lower
在您的集合中,而Upper
则不在。{1}}。您现在可以在Lower
和Upper
之间进行二进制搜索,以查找限制。这看起来像O(log n * O(测试))复杂性。
如果您知道Upper
介于50和100之间,请在这两个值之间进行二元搜索。
如果你有随机间隙并且你知道上限是100最大值我怀疑你做得比从那里开始并逐个测试每个数字要好,直到test()
在你的集合中找到一个值。 / p>
如果你有随机差距并且不知道上限,那么你永远不会确定你找到了上限。
答案 3 :(得分:0)
也许你应该遍历它?这将是O(n)复杂。我认为没有其他办法可以做到这一点。
答案 4 :(得分:0)
你知道预先设定的尺寸吗?
实际上,我猜你可能没有 - 否则第一个问题就是微不足道了。
如果你知道这套装置有多大,那会有所帮助。
对于你没有这种能力的差距 - 你甚至无法判断你何时找到了最大的元素。 (除非你知道最大间隙大小)
答案 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?