使用递归的阶乘(回溯与新方法)

时间:2019-04-08 15:03:04

标签: c++14

我正在尝试学习递归。对于它的起始问题(即计算一个阶乘),我已经使用两种方法完成了它。 第一个是通常的常规方法。 第二个我尝试做一些不同的事情。 在第二个中,我在结尾处返回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

1 个答案:

答案 0 :(得分:1)

首先,我想指出的是,以牺牲可读性为代价的过早优化几乎总是一个错误,特别是当对优化的需求来自于直觉而不是测量时。

  

“我们应该忘记效率低下的问题,大约有97%的时间是这样:过早的优化是万恶之源。但是,我们不应该在那3%的临界水平上放弃自己的机会”-唐纳德·克努斯(Donald Knuth)

但是,假设在这种情况下,我们关心的是3%,因为我们的程序所做的只是计算大量阶乘。简而言之:您将永远比编译器更聪明。

如果这看起来有点疯狂,那么这绝对适用于您,您应该停止考虑“微管理/优化代码”。如果您是一位非常熟练的C ++程序员,那么在大多数情况下,这仍然适用于您,但是您会认识到有机会帮助您的编译器。

要用某种事实证明这一点,我们可以编译代码(使用自动优化),并(大致)比较汇编输出。我将使用精彩的网站godbolt.org

不要因为疯狂的汇编代码而灰心,我们不需要了解它。但是我们可以看到两种方法

  1. 作为汇编代码编译时的长度基本相同
  2. 包含几乎相同的说明

因此,回顾一下,可读性应该是您的第一要务。如果速度测量表明代码的这一部分确实是一个很大的性能问题,请认真考虑是否可以进行结构上改进算法的更改(即通过降低复杂性)。否则,编译器会为您处理。