这是我一直在考虑的事情:假设你有一个数字,x,可以是无限大,你必须找出它是什么。所有你知道的是,如果另一个数字y大于或小于x。什么是找到x的最快/最好的方法?
一个邪恶的对手选择了一个非常大的数字......说:
int x = 9^9^9^9^9^9^9^9^9^9^9^9^9^9^9
并提供isX
,isBiggerThanX
和isSmallerThanx
个功能。示例代码可能如下所示:
int c = 2
int y = 2
while(true)
if isX(y) return true
if(isBiggerThanX(y)) fn()
else y = y^c
其中fn()
是一个函数,一旦找到数字y(大于x)就会确定x(比如将数字除以一半并进行比较,然后重复)。问题是,由于x是任意大的,因此使用常数来增加y似乎是一个坏主意。
这是我一直想知道的一段时间,我想听听其他人的想法
答案 0 :(得分:6)
使用二进制搜索,就像通常的“尝试猜测我的号码”游戏一样。但由于没有有限的上限点,我们会在第一阶段找到合适的上端点:
X
与高端点进行比较。第一阶段本身类似于二元搜索。不同之处在于,不是每一步都将搜索空间减半,而是将其翻倍!每个阶段的成本为O(log X)
。一个小的改进是在每个加倍步骤设置低端点:我们知道X
至少与前一个高端点一样高,所以我们可以将它重用为低端点。搜索空间的大小在每一步仍然翻倍,但最终它将是原来的一半。二进制搜索的成本只会减少一步,因此其总体复杂性保持不变。
一些注释
回应其他评论时的几点说明:
这是一个有趣的问题,计算机科学不只是关于在物理机器上可以做什么。只要问题可以正确定义,就值得提出并思考。
数字的范围是无限的,但任何可能的神秘数字都是有限的。所以上面的方法最终会找到它。 最终定义,例如,对于任何可能的有限输入,算法将在有限数量的步骤内终止。然而,由于输入是无界的,步数也是无限的(只是在每种特定情况下,它将“最终”终止。)
答案 1 :(得分:3)
如果我正确地理解了你的问题(建议我不这样做),你问的是如何解决“从1到10中选择一个数字”,除了代替10,上限是无穷大。
如果您的数字空间真的无限,则以下情况属实:
int
(或任何其他数据类型)如果空间非常大但受到限制,我认为你能做的最好的就是二元搜索。从数字范围的中间开始。如果所需的数字变得更高或更低,则将该数字空间的一半除去,并重复直到找到所需的数字。
在您建议的实施中,您会引发y ^ c
。然而,无论选择多大c
,它都不会在无限空间内移动针。
答案 2 :(得分:1)
无限不是一个数字。因此,即使使用计算机也无法找到它。
答案 3 :(得分:1)
这很有趣。多年来我一直在想同样的事情,尽管我从来没有听过其他人提出这个问题。
就像您的方案一样简单,它似乎仍然提供的信息不足以允许选择最佳策略。所有人都可以选择合适的启发式方法。我的启发式方法是加倍y
,但我认为我更喜欢你。你们加倍log(y)
。
启发式的优点在于,只要整数适合计算机的内存,它就会在对数时间内找到合适的y
。
反的问题。找到y
后,您将如何处理?
答案 4 :(得分:1)
我同意使用二进制搜索,但我相信ONE-SIDED二进制搜索会更合适,因为这里的复杂性不会是O(log n)[其中n是允许数字的范围],但是(log k) - 其中k是对手选择的数字。
这将如下工作:(伪代码)
k = 1;
while( isSmallerThanX( k ) )
{
k = k*2;
}
// At this point, once the loop is exited, k is bigger than x
// Now do normal binary search for the range [ k/2, k ] to find your number :)
所以即使允许的范围是无穷大,只要你的数字是有限的,你应该能够找到它:)
答案 5 :(得分:1)
如果对手只使用更好的范例(例如,被压抑),那么tetration的方法可以保证花费比宇宙年龄更长的时间来找到答案。这就是你应该这样做的方式:
1
0
0
...每个时钟周期,使其可以说的最大数量(如果我们等待的时间几乎是永恒的话)是10 ^ BusyBeaver(10 ^ 100)。如果你允许它说更复杂的表达式,如eval(someprogram)
,power-towers,Ackermann的函数,无论如何 - 那么我相信这并不比将原来的10 ^ 100增加一些常数与你描述过(加上一些对数解释因子,见Kolmogorov复杂性)。所以让我们用另一种方式构建:
你的对手选择一个有限的可计算数字,并通过计算它给你一个函数告诉你数字是否更小/更大/相等。他还给你一个输出的表示(在一个理智的世界,这将是“你只能打印像99999这样的数字”,但他可以使它更复杂;它实际上并不重要)。 继续以位为单位测量此函数的大小。
现在,使用您自己的函数回答,该函数是其函数(以位为单位)的两倍,并打印出最大数字,同时保持代码长度小于2N位。 (你使用他选择的相同表示法:在一个你只能打印出像“99999”这样的数字的世界里,这就是你所做的。如果你能定义函数,它会稍微复杂一点。)
答案 6 :(得分:0)
我不明白这里的目的,但我这就是我的想法:
阅读你的评论,我想你不是在寻找无限大的数字,而是寻找“超大数”。无论数字是多少,都会有一个很大的数字。的数字。你如何得到它们,不是问题。记住这一点:
不需要复杂的计算。只需在数字键盘上键入随机键即可拥有超大号,然后让程序随机添加/删除/修改该数字的数字。你得到一个非常大的数字列表 - 从中选择任何一个。
例如:3672036025039629036790672927305060260103610831569252706723680972067397267209
and keep modifying/adding digits to get more numbers
PS:如果你清楚地说出问题的目的,我们或许可以给出更好的答案。