我正在尝试找到1到1000000之间的最大Collatz sequence。我在下面编写了以下代码。我想这是正确的,但它非常慢。你能给我一些提示,让它更快吗?感谢。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
bool myfn(int i, int j) { return i<j; }
int collatz(int x);
int main()
{
vector <int> myvector;
for(int i = 1; i < 1000000; i++)
{
myvector.push_back(collatz(i));
}
cout<<*max_element(myvector.begin(),myvector.end(),myfn);
return 0;
}
int collatz(int x)
{
int counter = 1;
while(1)
{
if(x == 1)
break;
if(x % 2 == 0)
{
x = x / 2;
counter++;
}
else
{
x = 3 * x + 1;
counter++;
}
}
return counter;
}
答案 0 :(得分:4)
实际上,我刚测试过,你的代码不只是“非常慢”,而是无限循环。不,你不仅反驳了Collatz猜想,但据我所知,你正遭受整数溢出。
更具体地说,在collatz(113383)
期间int x
变量由于溢出而变为负数:
551580299 1654740898 827370449 -1812855948 -906427974 -453213987
在此之后不久,它开始循环以下序列,因此永远不会退出循环
-37 -110 -55 -164 -82 -41 -122 -61 -182 -91 -272 -136 -68 -34 -17 -50 -25 -74 -37 ...
将int x
参数更改为long long
后,程序很快就完成了。
当然,问题仍然是不会发生不会导致无限循环并且不被注意的溢出,因为您仍然会得到错误的答案。但是,在放了
之后if (x < 0) {
cout << "ERROR" << endl;
}
在while(1)
循环的末尾并且看不到任何输出,我认为你可以确信long long
对于数字1到1000000(8字节)的Collatz序列足够大在我的计算机上,与int
的4个字节相比,如果你有兴趣的话。)
编辑: 作为旁注:如果您只需要最大值,我认为没有任何理由保留所有结果的向量。以下代码会占用更少的内存:
int maxCollatz = 0;
for(int i = 1; i < 1000000; i++) {
if (i % 10000 == 0)
cout << i << endl;
maxCollatz = max(maxCollatz, collatz(i));
}
另一个注意事项:你实际上只是从1到999999循环,所以如果100万的Collatz序列是最长的,你可能会错过那个......
答案 1 :(得分:2)
以下是一些提示:
将矢量初始化为您的容量。
在推动元素时,矢量可能正在扩展。最糟糕的情况是,每次push_back重新分配一次。
将矢量视为数组
将向量初始化为其容量后,可以使用运算符[]访问向量槽而不是调用push_back
。
优化collatz
这可能是你的瓶颈。尝试放入一个单独的文件,并在其上启动编译器优化。
可能有更优化的算法。