【问题标题】:What is wrong with my Catalan Number logic?我的加泰罗尼亚数字逻辑有什么问题?
【发布时间】:2011-04-19 14:01:29
【问题描述】:

我想为加泰罗尼亚数字写一个代码。加泰罗尼亚数字定义如下:

C(n) = 2n C n/(n+1)。但我不想计算 (2n C n),而是想使用以下事实自下而上计算加泰罗尼亚语数字:

Catalan(n) =    
2n! /n! * n! * (n+1)  

Catalan(n+1) =  
2*(n+1)  
--------------------------- =    
(n+1)! * (n+1)! * ((n+1)+1)  

(2n+2) * (2n+1) * 2n!    
------------------------------- =  
(n+1) * n! * (n+1) * n! * (n+2)    

(2n+2) * (2n+1) * 2n!    
----------------------------------- =    
(n+1) * (n+2) * n! * n! * (n+1)    

(2n+2) * (2n+1)    
--------------- * Catalan(n)      
(n+1) * (n+2)

现在利用上述事实,这是我的以下代码:

int catalan(int n)
{
    if (n == 1)
       return 1 //since c(1)=1 is my base case
    else
       return (((2*n+2) * (2*n+1))/((n+1)*(n+2))) * catalan(n-1)
}

现在,我的问题是为什么当我的输入为 4 时,上述函数会返回 12。它应该返回 14,因为 c(4)=14。

有人可以帮帮我吗?

【问题讨论】:

  • (2n C n) 应该是什么意思?
  • @Jens Schauder 二项式系数:n 上的 2n

标签: c algorithm math catalan


【解决方案1】:

尽管C(n) 的原始表达式可能是错误的,但实际的重复出现

正确

你可以进一步简化为

但这给了你C(n+1)C(n)。你想要的是C(n),就C(n-1)而言。插入n-1获取

还要注意,为了防止整数除法截断你的结果,你需要先乘然后除。

int catalan(int n) {
  if (n == 1)
    return 1; 
  else
    return 2 * (2*n - 1) * catalan(n-1) / (n+1);
}

编辑:如果需要经常使用 的值而不是只计算一次,那么使用memoization 可能是个好主意,以避免多次计算它们。

此外,请注意,由于增长率较大,加泰罗尼亚数字会迅速溢出C 具有的任何预定义整数数据类型。

【讨论】:

    【解决方案2】:

    根据http://en.wikipedia.org/wiki/Catalan_number,递推公式为:

    C(n+1)=2(2n+1)/(n+1) * C(n)C(n)=2(2(n-1)+1)/n * C(n-1)

    我想你已经忘记了从 C(n+1)C(n) 的转换。

    【讨论】:

    • 这就是他所拥有的——他刚刚替换了 (n+1)!与 (n+1)*n!
    • 公式是对的,只是编程的时候走心了。
    • 确实,问题不存在。
    【解决方案3】:

    您的公式中有错误。您的公式用于计算 c(n+1) 但您的输入是 n。这可以通过在计算中使用之前将 n 的值减一来解决:

    int catalan(int n)
    {
        if (n == 1)
           return 1 //since c(1)=1 is my base case
        else
           n=n-1
           return (((2*n+2) * (2*n+1))/((n+1)*(n+2))) * catalan(n)
    }
    

    编辑: 正如 abeln 所指出的,上面的代码将由于整数除法丢弃余数而失败。请改用以下代码:

    int catalan(int n)
    {
        if (n == 1)
           return 1 //since c(1)=1 is my base case
        else
           n=n-1
           return ((catalan(n) * (2*n+2) * (2*n+1))/((n+1)*(n+2)))
    }
    

    【讨论】:

    • 这里的代码会因为整数除法的截断而产生不正确的值。
    【解决方案4】:

    当您从数学表达式转到代码时,您是在 Catalan() 部分中将 n 隐式替换为 n-1,而不是在表达式本身中。因此,您正在计算值 N 的乘数并将其乘以 C(N-1)。尝试用 N-1 代替等式中的 N,这会导致:

    int catalan(int n)
    {
        if (n == 1)
           return 1 //since c(1)=1 is my base case
        else
           return (((2*n) * (2*n-1))/((n)*(n+1))) * catalan(n-1)
    }
    

    【讨论】:

    • 你测试过你的功能吗?
    【解决方案5】:

    在你的公式中,你有

             (2n)!
    C(n) = ----------------
            (n+1)! * n! * n!
    

    实际上加泰罗尼亚数字被定义为

             (2n)!
    C(n) = ----------------
            (n+1)! * n!
    

    即你在分母上的一个阶乘太多了

    【讨论】:

    • 同理,因为2n c n /n+1 = 2n!/n!*n!*(n+1)。现在,分母被简化为n+1! = n!*(n+1),并被替换为那里。都是一样的。
    猜你喜欢
    • 2015-05-24
    • 2017-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-26
    • 1970-01-01
    • 2012-04-19
    相关资源
    最近更新 更多