【问题标题】:Why is codechef not accepting my solution if i use recursion?如果我使用递归,为什么 codechef 不接受我的解决方案?
【发布时间】:2021-08-07 14:17:19
【问题描述】:

所以,最近我在一个使用递归的竞争性编码网站上解决了阶乘问题。但是在提交它时会拒绝我的解决方案,而在使用简单的 for 循环时它只会接受它。我读过很多地方说递归比循环慢,但我仍然不确定我的代码是因为递归而被拒绝还是真的有问题。不过,我的代码在 IDE 中运行良好。

这是我使用递归的代码。

更新:好吧,我问我的一位朋友可能是什么原因。所以原因是问题中n的范围被赋予了1000。如果我使用递归,那么阶乘必须存储不可能的数据(如果 n==1000),因为 int 不能存储那么多(1000 的阶乘),即为什么不接受递归。 我是 S.O 的新手,如果问题没有得到正确解释,我很抱歉,下次我会尝试更详细地询问,以免被否决。

 int factorial(int n)
    {
        
        if(n>1)
        {
            return n*factorial(n-1);
        }
        else
        {
            return 1;
        }
    }

int main() {
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
       cout<< factorial(n);
    }
    return 0;

【问题讨论】:

  • 您确定在循环版本中使用了int 吗?我问是因为阶乘会很快溢出 32 位整数。看起来如果n 大于 12,你就会溢出,因为 13! 6227020800 对于 32 位 int 来说太大了。参考:en.wikipedia.org/wiki/Factorial
  • 我的代码在 IDE 中运行良好。 -- Are you sure?。顺便说一句,你得到的所有反对票的可能原因是因为你没有做一个简单的测试,就像我链接到的那样。
  • 如果 n1000 显然这两种方法都不能正常工作。 1000! 是一个很大的数字。比语言或系统的最大int 变量大得多。您需要使用大型 int 库或编写自己的库。最有可能的是 20 是最大的 n,它可以在没有大型 int 库的情况下工作。

标签: c++


【解决方案1】:

您的代码看起来可以正常工作,正如您所说,您的测试证实了这一点。因此,我们想知道拒绝的原因可能是什么。为了保持这个客观,让我们客观地说。那么,循环递归的客观缺点是什么?

堆栈

函数调用存储在称为堆栈的内存部分中。当您编写一个具有太多自调用的递归函数时,无论是由于尾号错误(该函数不知道何时停止)或由于真正需要重复多次操作,那么您会浪费大量内存通过将所有调用存储在堆栈中。堆栈有一个限制,如果超过这个限制,就会发生 stackoverflow 错误(请参阅此站点的名称)。相反,在阶乘的情况下,基于循环的迭代方法,它可以使用索引(在给定时刻要乘以的数字)和结果(到目前为止)。因此,与其在堆栈中存储与输入一样多的函数调用并浪费大量资源,您可以根据 2 个数字获得解决方案:

while (n > 1) product *= n--;

好的,由于阶乘很快达到非常大的数字,您仍然可能遇到数据溢出问题。

可维护性

程序员在编写递归函数时比在编写循环时更容易陷入死胡同。

【讨论】:

  • 由于阶乘很快溢出整数或长整数我怀疑我们有堆栈溢出。
  • @drescherjm 为什么我们要排除 n 非常大的情况,比如 100 000?在这种情况下,数据溢出会导致混乱、不希望的结果,这是真的,但你也会得到一个 SO。
  • n 只能为 20 或更少,代码才能在不溢出 64 位整数范围的情况下工作。在 21 处,您大于 64 位整数。如果使用大型数学库但代码使用 int 而不是大型数学库,我同意你的看法。
  • @drescherjm 那我换个方式解释吧。是的,经过很少的步骤,代码将由于数据溢出而出现错误。但这并不能阻止算法到达 stackoverflow。是的,由于数据溢出,经过几步之后,将乘积与 n 相乘将产生比以前更小的值。但是数据溢出不会停止递归,它会继续运行直到抛出 SO。
  • int 会比栈溢出快得多,而且技术上有符号整数溢出是 UB,所以 stackoverflow 不相关
猜你喜欢
  • 2017-01-30
  • 2011-09-08
  • 2021-10-01
  • 2021-08-17
  • 2021-06-23
  • 1970-01-01
  • 2017-08-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多