几点:
1. 在问题规模大的时候,一定要检查选择的数据类型是否够用,会不会overflow。这里的case就是一个很好的例子。我的算法几分钟就写好了,也蛮正确的,除了对于start num i及chain中的number n的数据类型选择了int,这就导致在n被3n+1反复搞大后,超出了int的范围,变成了负数,也就进入了导致算不出结果来的死循环里(因为永远也算不到1了)。所以,切记:问题规模大的时候,一定仔细考虑清楚数据类型的选择。
2. unsigned int的数据参与大规模运算要比long long快3倍以上。这里指的是仅仅替换i和n的数据类型。
3. 在看到更多规律的基础上,我加了个map来试图减少一些运算,结果:在题目要求的1million的问题规模下,配合unsigned int的正确类型,算不出;在调整到1000以验证算法正确性的实验中,还是发现:使用map后,由于要多做很多排序和查找的工作,虽然节省了一些直接的chain中number的计算,但最终时间统计显示还是比不用map要慢。所以,在你确定要使用map时,务必考虑清楚你增加的运算和减少的运算之间的关系,不见得能改善多少算法性能,而且还容易产生副作用。算法时间复杂度的本质在于:其需要执行的基本运算的次数的多少。
4. oh,my!我终于意识到:位操作要比乘除运算高效的多!在算法中,用n&1替换n%2来判断奇数偶数,时间花费从3秒多减少到了1秒左右!这个例子,我印象很深刻,非常有意义的实验。感谢problem 14 answer thread里的兄弟的启发。
下面附上代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream>
#include <map>
#include <ctime>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
clock_t startT = clock();
int maxNum = 10; // initialized with starting number 13's chain length.
unsigned int theStartNum = 13;
unsigned int n = 0; // Be exact to choose its data type.
for(unsigned int i = 14; i < 1000000; i++)
{
n = i;
int tempNum = 0;
while(true) // to calculate tempNum.
{
// if(n%2) // odd. Using this, whole algorithm cost >3s.
if(n&1) // using this, cost 1s or so.
{
n = 3*n + 1 ;
}
else // even.
{
if(n == 16) // minor optimization.
{
tempNum += 4;
break;
}
else
n /= 2;
}
tempNum++;
if(n == 1)
break;
}
if(maxNum < tempNum)
{
maxNum = tempNum;
theStartNum = i;
}
}
clock_t endT = clock();
double spentT = difftime(endT, startT);
cout << "theNum is: " << theStartNum << endl;
cout << "theChain: " << maxNum << endl;
cout << "spentT:" << spentT << endl;
return 0;
}
#include <map>
#include <ctime>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
clock_t startT = clock();
int maxNum = 10; // initialized with starting number 13's chain length.
unsigned int theStartNum = 13;
unsigned int n = 0; // Be exact to choose its data type.
for(unsigned int i = 14; i < 1000000; i++)
{
n = i;
int tempNum = 0;
while(true) // to calculate tempNum.
{
// if(n%2) // odd. Using this, whole algorithm cost >3s.
if(n&1) // using this, cost 1s or so.
{
n = 3*n + 1 ;
}
else // even.
{
if(n == 16) // minor optimization.
{
tempNum += 4;
break;
}
else
n /= 2;
}
tempNum++;
if(n == 1)
break;
}
if(maxNum < tempNum)
{
maxNum = tempNum;
theStartNum = i;
}
}
clock_t endT = clock();
double spentT = difftime(endT, startT);
cout << "theNum is: " << theStartNum << endl;
cout << "theChain: " << maxNum << endl;
cout << "spentT:" << spentT << endl;
return 0;
}