我正在尝试学习递归。对于它的起始问题(即计算一个阶乘),我已经使用两种方法完成了它。 第一个是通常的常规方法。 第二个我尝试做一些不同的事情。 在第二个中,我在结尾处返回n的值,而不是像第一个使用回溯的情况那样获得起始值。 我的问题是,我的方法比回溯有什么优势吗? 是否要求选择哪个是更好的解决方案?
//第一个是,
ll factorial(int n)
{
if(n==1)
return 1 ;
return n*factorial(n-1) ;
}
int main()
{
factorial(25) ;
return 0 ;
}
//第二个是,
ll fact(ll i,ll n)
{
if(i==0)return n ;
n=(n*i)
i--;
n=fact(i,n);
}
int main()
{
int n ;
cin>>n ;
cout<<fact(n,1) ;
return 0 ;
}
// ll is long long int
答案 0 :(得分:1)
首先,我想指出的是,以牺牲可读性为代价的过早优化几乎总是一个错误,特别是当对优化的需求来自于直觉而不是测量时。
“我们应该忘记效率低下的问题,大约有97%的时间是这样:过早的优化是万恶之源。但是,我们不应该在那3%的临界水平上放弃自己的机会”-唐纳德·克努斯(Donald Knuth)
但是,假设在这种情况下,我们关心的是3%,因为我们的程序所做的只是计算大量阶乘。简而言之:您将永远比编译器更聪明。
如果这看起来有点疯狂,那么这绝对适用于您,您应该停止考虑“微管理/优化代码”。如果您是一位非常熟练的C ++程序员,那么在大多数情况下,这仍然适用于您,但是您会认识到有机会帮助您的编译器。
要用某种事实证明这一点,我们可以编译代码(使用自动优化),并(大致)比较汇编输出。我将使用精彩的网站godbolt.org
不要因为疯狂的汇编代码而灰心,我们不需要了解它。但是我们可以看到两种方法
因此,回顾一下,可读性应该是您的第一要务。如果速度测量表明代码的这一部分确实是一个很大的性能问题,请认真考虑是否可以进行结构上改进算法的更改(即通过降低复杂性)。否则,编译器会为您处理。