我需要猜一个数字。我只能看看我提议的数字是低还是高。性能很重要,所以我想到了以下算法:
假设我猜的数字是600。
我从数字1000开始(或者更高的性能,以前数字的平均结果)。
然后检查1000是高于还是低于600.它更高。
然后我将数字除以2(现在为500),并检查它是否低于或高于600.它更低。
然后我找到差异并按以下方式将其除以2以检索新数字:((1000 - 500)/ 2)。结果是750.然后检查那个号码。
等等。
这是最好的方法吗?有更聪明的方法吗?对于我的情况,每次猜测大约需要500毫秒,我需要在尽可能短的时间内猜测很多数字。
我可以粗略地假设先前猜测的平均结果也接近即将到来的数字,所以我可以使用一种模式来为自己的利益。
答案 0 :(得分:7)
是binary search
是最有效的方法。 Binary Search
就是您所描述的。对于在Binary Search
时间内运行1到N O(log(n))
之间的数字。
所以这是找到1-N
之间的数字的算法int a = 1, b = n, guess = average of previous answers;
while(guess is wrong) {
if(guess lower than answer) {a = guess;}
else if(guess higher than answer) {b = guess;}
guess = (a+b)/2;
} //Go back to while
答案 1 :(得分:3)
嗯,你在没有额外信息的情况下采取了最好的方法 - 基本上是二进制搜索。
你如何使用“以前猜测的平均结果”取决于你;它会建议将结果偏向该平均值,但您需要对先前结果的指示进行分析,以便找出最佳方法。不要只使用平均值:使用完整的分布。
例如,如果所有结果都在600-700范围内(即使假设范围达到1000),平均值为670,那么您可能以<6>开始但是如果它说“猜得更高”然后你可能想要选择670到700之间的值作为你的下一个猜测,而不是835(很可能高于实际结果)。
我建议您记录之前查询的所有结果,这样您就可以将其用作替代方法的测试数据。
答案 2 :(得分:1)
通常,从范围的中间点开始的二分搜索是最佳策略。但是,您有其他特定信息可能会使其成为次优策略。这主要取决于“接近先前结果的平均值”的含义。
如果数字接近先前的平均值,则在第二步中除以2不是最佳的。
示例:之前的数字630,650,620,660。您从640开始。
你的号码实际上更接近了。想象一下它是634。
数字较低。如果在第二步中除以2,则得到320,从而失去对先前平均数的任何优势。
您应该进一步分析行为。在您的特定情况下,从N个先前数字的平均值开始,然后添加或减去与先前数字的标准差相关的一些数量可能是最佳的
答案 3 :(得分:1)
是的,二进制搜索(您的算法)在这里是正确的。但是,标准二进制搜索中缺少一件事:
对于二进制搜索,您通常需要知道要搜索的最大值和最小值。如果您不知道这一点,您必须在开头迭代地找到最大值,如下所示:
当你总是乘以2时,你会比线性搜索时快得多。
答案 4 :(得分:0)
您知道可能值的范围吗?如果是,请始终从中间开始,完全按照您的描述进行操作。
答案 5 :(得分:0)
0到N之间的标准二进制搜索(N是给定数字)将在logN时间内给出答案。
答案 6 :(得分:0)
int a = 1, b = n+1, guess = average of previous answers;
while(guess is wrong) {
if(guess lower than answer) {a = guess;}
else if(guess higher than answer) {b = guess;}
guess = (a+b)/2;
} //Go back to while
You got to add +1 to n else you can never get n since it's an int.