最近我一直在解决来自Google Foobar的一些挑战,现在我已经被困在其中一个超过4天了。它是关于递归函数定义如下:
R(0) = 1
R(1) = 1
R(2) = 2
R(2n) = R(n) + R(n + 1) + n (for n > 1)
R(2n + 1) = R(n - 1) + R(n) + 1 (for n >= 1)
挑战在于编写一个函数answer(str_S)
,其中str_S
是整数S的基数为10的字符串表示形式,它返回最大n
个R(n) = S
。如果没有这样的n,则返回"无"。此外,S将是一个不大于10 ^ 25的正整数。
我已经研究过很多关于递归函数和解决递归关系的问题,但没有运气。我输出了前500个数字,但我发现每个数字都没有任何关系。我使用了下面的代码,它使用了递归,所以当数字开始变大时,它变得非常慢。
def getNumberOfZombits(time):
if time == 0 or time == 1:
return 1
elif time == 2:
return 2
else:
if time % 2 == 0:
newTime = time/2
return getNumberOfZombits(newTime) + getNumberOfZombits(newTime+1) + newTime
else:
newTime = time/2 # integer, so rounds down
return getNumberOfZombits(newTime-1) + getNumberOfZombits(newTime) + 1
挑战还包括一些测试用例,所以这里是:
Test cases
==========
Inputs:
(string) str_S = "7"
Output:
(string) "4"
Inputs:
(string) str_S = "100"
Output:
(string) "None"
我不知道我是否需要解决任何更简单的复发关系,但由于有一个偶数和一个奇数,我觉得很难做(我还没有学到关于它在学校,所以我所知道的关于这个主题的一切都来自互联网文章。)
所以,任何指导我完成这一挑战的帮助都将受到欢迎:)
答案 0 :(得分:1)
我没有尝试用数学方法简化这个函数,而是简化了Python中的算法。正如@LambdaFairy所建议的那样,我在getNumberOfZombits(time)函数中实现了memoization。这种优化加快了很多的功能。
然后,我进入下一步,试图看看那些兔子的输入是什么。我之前通过观察它的情节分析了这个函数,我知道偶数数字首先得到更高的输出,并且只有在一段时间之后奇数才达到相同的水平。由于我们想要输出的最高输入,我首先需要搜索偶数,然后搜索奇数。
正如您所看到的,奇数总是花费比偶数更多的时间来达到相同的输出。
问题是我们无法搜索每次增加1的数字(它太慢)。我要解决的是实现类似二分搜索的算法。首先,我会搜索偶数(使用二进制搜索算法),直到我找到一个答案或者我没有更多数字要搜索。然后,我对奇数进行了相同的操作(同样,使用二进制搜索算法),如果找到了答案,我就用它取代之前的任何东西(因为它必然比之前的答案更大)。
我有我用来解决此问题的源代码,所以如果有人需要它,我不介意分享它:)
答案 1 :(得分:0)
解决这个难题的关键是使用二分搜索。
从序列生成器可以看出,它们依赖于大约n / 2的递归,因此计算R(N)需要大约2 * log2(N)个递归调用;当然,你需要为奇数和偶数做这件事。
这不算太糟糕,但你需要弄清楚在哪里搜索N会给你输入。为此,我首先实现了对N的上限和下限的搜索。我以2的幂向上走N,直到我有N和2N分别为每个序列(奇数和偶数)形成下限和上限。 / p>
通过这些界限,我可以在它们之间进行二元搜索,以快速找到N的值,或者它不存在。