三拼的解释和时间/空间复杂性

时间:2014-02-24 18:53:30

标签: c algorithm math big-o combinatorics

我无法理解下面的解决函数究竟发生了什么。我知道它做了什么,但是我仍然不清楚 - 我无法想象它,或只是让自己理解它。有人可以解释一下吗?

原始问题陈述(link):

  

你可以用多少种方法用2x1多米诺骨牌拼成3xn矩形?

     

这是一个3x12矩形的样本平铺。

     

代码(取自here):

#include <stdio.h>
int dp[32];
int solve(int n)
{
    if(dp[n]!=-1)
        return dp[n];
    else
    {
        int i;
        int res = 3*solve(n-2);
        for(i=4;i<=n;i+=2)
            res+=2*solve(n-i);
        return dp[n]=res;
    }
}
int main()
{
    int i;
    for(i=0;i<32;i+=2)
        dp[i]=-1;
    for(i=1;i<32;i+=2)
        dp[i]=0;
    dp[0]=1;
    scanf("%d",&i);
    while(i!=-1)
    {
        printf("%d\n",solve(i));
        scanf("%d",&i);
    }
    return 0;
}

另一件事是,这个算法的时间和空间复杂度是多少?由于它是一个递归函数,它可能是O(log N),但我也不确定。

1 个答案:

答案 0 :(得分:1)

从技术上讲,运行时是O(1),因为输入的大小有一个上限(特别是32)。但是我们假设一分钟问题的大小不超过32,并考虑这个问题。在这种情况下,运行时为O(n 2 )。在进行了一些大小的递归调用之后,任何将来的相同大小的递归调用都会在时间O(1)中运行。这是由于在dp表中使用了memoization。这意味着我们可以通过总结所有可能的递归调用来计算总运行时间,即填充dp表所需的时间。

在大小为n的调用中,完成O(n)工作以填充数组。你可以通过从4开始的for循环来看到这个,并且在每个执行O(1)工作的点上向上计数n到2。由于递归调用的大小为0,1,2,...,n,因此我们有O(n)个调用O(n)调用,每个调用总共为O(n 2 )工作

希望这有帮助!