建议分析算法

时间:2015-03-05 00:12:17

标签: algorithm recursion time-complexity asymptotic-complexity

我最近一直在练习分析算法。我觉得我对分析非递归算法非常了解,但我不确定,并且刚刚开始全面理解递归算法。虽然,我还没有对我的方法进行正式检查,以及我一直在做的事情是否正确

要问某人是否可以查看我已经实施和分析的一些算法,看看我的理解是否正确,或者我是否完全关闭,会不会太过分。

这里:

1)

sum = 0;
for (i = 0; i < n; i++){
    for (j = 0; j < i*i; j++){
        if (j % i == 0) {
            for (k = 0; k < j; k++){
                sum++;
            }
        }
    }
}

我对这一个的分析是O(n ^ 5),原因是: Sum(i = 0到n)[Sum(j = 0到i ^ 2)[1的和(k = 0到j)]] 评估为: (1/2)(n ^ 5/5 + n ^ 4/2 + n ^ 3/3 - n / 30)+(1/2)(n ^ 3/3 + n ^ 2/2 + n / 6 )+(1/2)(n ^ 3/3 + n ^ 2/2 + n / 6)+ n + 1。 因此它是O(n ^ 5)

这是否正确评估循环的总结?

三重求和。我假设if语句总是会通过更糟糕的案例复杂性。对于最坏情况,这是正确的假设吗?

2)

int tonyblair (int n, int a) {
    if (a < 12) {
        for (int i = 0; i < n; i++){
            System.out.println("*");
        }
        tonyblair(n-1, a);
    } else {
        for (int k = 0; k < 3000; k++){
            for (int j = 0; j < nk; j++){
                System.out.println("#");
            }
        }
    }
 }

我对这个算法的分析是O(无穷大),因为if语句中的无限递归,如果它被假定为真,那将是最坏的情况。虽然,对于纯粹的分析,我分析了这是不是真的并且if语句不会运行。然后我得到了O(nk)的复杂性,原因是:

总和(k = 0到3000)[Sum(j = 0到nk)为1] 然后评估为nk(3001)+ 3001.因此是O(nk),其中k由于控制循环的迭代次数而不被丢弃。

1 个答案:

答案 0 :(得分:4)

第1名

我无法告诉您如何推导出您的公式。通常在算法中有多个步骤时添加术语,例如预先计算数据然后从数据中查找值。相反,嵌套for循环意味着乘法。此外,最糟糕的情况是这段代码的最佳情况,因为给定n值,sum将在结尾处相同。

为了找到复杂性,我们希望找到内循环的计算次数。如果从1到n,摘要通常很容易解决,所以我稍后会从它们中删除0。如果i为0,则中间循环不会运行,如果j为0,则内循环不会运行。我们可以将代码等效地重写为:

sum = 0;
for (i = 1; i < n; i++)
{
    for (j = 1; j < i*i; j++)
    {
        if (j % i == 0) 
        {
            for (k = 0; k < j; k++)
            {
                sum++;
            }
        }
    }
}

我可以通过迫使外环从2开始让我的生活更加艰难,但我不会去。外循环现在从1到n-1。中间循环基于i的当前值运行,因此我们需要进行求和:

enter image description here

中间for循环总是进入(i ^ 2 - 1),j只能被i整除,共计(i - 1)次(i,i * 2,i * 3,... ,i *(i-2),i *(i-1))。有了这个,我们得到:

enter image description here

然后中间循环执行j次。我们求和中的j与代码中的j不同。求和中的j表示每次中间循环执行时。每次中间循环执行时,代码中的j将为(i * (number of executions so far)) = i * (the j in the summation)。因此,我们有:

enter image description here

我们可以将i移动到两个求和之间,因为它是内求和的常量。然后,1到n之和的公式是众所周知的:n*(n+1)/2。因为我们要去n - 1,所以我们必须减去n。这给出了:

enter image description here

平方和和立方总和的总和也是众所周知的。记住我们在两种情况下只求n-1,我们必须记得分别减去n ^ 3和n ^ 2,我们得到:

enter image description here

这显然是n ^ 4。如果我们一路解决,我们得到:

enter image description here

第2名

对于最后一个,实际上是O(无穷大),如果a&lt; 12因为if语句。好吧,从技术上讲,一切都是O(无穷大),因为Big-O只提供运行时的上限。如果&lt; 12,它也是欧米茄(无限)和theta(无限)。如果只有else运行,那么我们得到i * n的1到2999的总和:

enter image description here

注意从1到2999的总和是一个常数(它的4498500)是非常重要的。无论常数有多大,它仍然是常数,而不依赖于n。我们最终将它从运行时计算中抛弃。有时,当理论上快速算法具有大常数时,它实际上比理论上慢的其他算法慢。我能想到的一个例子是Chazelle's linear time triangulation algorithm。从来没有人实现它。无论如何,我们有4498500 * n。这是theta(n):

enter image description here