这取决于您要计算的值有多大。对于n <= 50000,以下工作:
#include <cmath>
/*
*/
round(1.201*pow(n, 0.618));
事实证明,由于这个序列的性质,您几乎需要其中的每一个条目来计算 g[n]。我编写了一个解决方案,使用map 保存过去的计算,清除不需要的值。对于n == 500000,映射仍然有大约496000 条目,并且由于映射有两个值,而数组应该有一个值,因此您最终会使用大约两倍的内存。
#include <iostream>
#include <map>
using namespace std;
class Golomb_Generator {
public:
int next() {
if (n == 1)
return cache[n++] = 1;
int firstTerm = n - 1;
int secondTerm = cache[firstTerm];
int thirdTerm = n - cache[secondTerm];
if (n != 3) {
auto itr = cache.upper_bound(secondTerm - 1);
cache.erase(begin(cache), itr);
}
return cache[n++] = 1 + cache[thirdTerm];
}
void printCacheSize() {
cout << cache.size() << endl;
}
private:
int n = 1;
map<int, int> cache;
};
void printGolomb(long long n)
{
Golomb_Generator g{};
for (int i = 0; i < n - 1; ++i)
g.next();
cout << g.next() << endl;
g.printCacheSize();
}
int main()
{
int n = 500000;
printGolomb(n);
return EXIT_SUCCESS;
}
你可以猜到很多。 n - g(g(n - 1)) 使用 g(n-1) 作为 g 的参数,它总是比 n 小得多。同时,递归也使用n - 1作为参数,与n接近。你不能删除那么多条目。
在没有 O(n) 内存的情况下,你可以做的最好的事情是递归结合对更小的n 准确的近似值,但它仍然会很快变慢。此外,随着递归调用的叠加,您可能会使用比适当大小的数组更多的内存。
不过,您也许可以做得更好。序列增长非常缓慢。将这一事实应用于g(n - g(g(n - 1))),您可以说服自己,这种关系主要需要更接近1 的存储值和更接近n 的存储值——nearN(n - near1(nearN(n - 1)))。您可以在两者之间有大量不需要存储的数据,因为它们将用于g(n) 的计算,比您关心的要大得多的n。下面是维护g 的第一个10000 值和g 的最后一个20000 值的示例。它至少对n <= 2000000 有效,并且在n >= 2500000 肯定会停止工作。对于n == 2000000,计算大约需要 5 到 10 秒。
#include <iostream>
#include <unordered_map>
#include <cmath>
#include <map>
#include <vector>
using namespace std;
class Golomb_Generator {
public:
int next() {
return g(n++);
}
private:
int n = 1;
map<int, int> higherValues{};
vector<int> lowerValues{1, 1};
int g(int n) {
if(n == 1)
return 1;
if (n <= 10000) {
lowerValues.push_back(1 + lowerValues[n - lowerValues[lowerValues[n - 1]]]);
return higherValues[n] = lowerValues[n];
}
removeOldestResults();
return higherValues[n] = 1 + higherValues[n - lowerValues[higherValues[n - 1]]];
}
void removeOldestResults() {
while(higherValues.size() >= 20000)
higherValues.erase(higherValues.begin());
}
};
void printGolomb(int n)
{
Golomb_Generator g{};
for (int i = 0; i < n - 1; ++i)
g.next();
cout << g.next() << endl;
}
int main()
{
int n = 2000000;
printGolomb(n);
return EXIT_SUCCESS;
}