在算法中直接计算数学

时间:2012-09-13 14:19:23

标签: java algorithm math

我试图在我的算法中使数学正确,但我很难理解计算的“算法分析”,即f(n) = 1f(n) = n-1等。

我创建了一个循环遍历排序整数数组的方法,并计算有多少个不同的整数(即{1,3,3,3,5,6,8} = 5)。如何计算最坏情况?

基本上,代码是这样的:

int length = a.length;
int diffCount = 1; //The number of different integers

for(int i = 1; i < length; i++)
{
    int b = a[i];
    int c = a[i-1];

    if(c>b)
         throw new IllegalStateException("unsorted array");

    if(c!=b)
         diffCount++;
}
return diffCount;

还有一些其他的东西,但这只是为了防止像空数组这样的错误,所以我没有包含它。

这里最糟糕的情况是什么?如果条件c!=b每次都为真?

3 个答案:

答案 0 :(得分:4)

就运行时分析而言,如果对数组进行排序,则此算法始终为 O(n)。如果没有,它会在此之前抛出异常(但最坏的情况仍然是 O(n))。

取决于值,结果略有不同。请参阅Peter的答案,了解分支预测的解释。但我不认为这会显着影响运行时间。

答案 1 :(得分:1)

理论上,对于给定长度的数组,执行此循环所需的时间总是相同的。

我查看了分支预测是否会受到影响,在这种情况下它似乎不可能因为JIT足够聪明以消除第二个分支。

在C中,可以使用

删除分支
diffCount += c != b;

可能JIT做了类似的事情。

答案 2 :(得分:1)

通常,在分析复杂性时,请关注您认为算法中最慢的操作。对于排序算法,我相信你选择比较。在您的代码中,我将选择两个数组访问:

int b = a[i];
int c = a[i-1];

甚至比较两者:

if (c != b) …

而不是diffCount++。这意味着比较的结果并不重要,因为它总是会发生。

当然,您可以选择分析多个操作的复杂性。例如。对于排序,您可以查看元素交换以及元素比较。或者在您的情况下,您可能希望专注于diffCount++因为您希望内存写入比比较慢得多。

我选择的操作会被a.length次点击,这就是算法的复杂性。

如果这个选择的操作处于一个条件下,你必须选择(当寻找Big-O复杂性时)一个合理的上限限制条件可以被击中的频率。因此,在您的情况下,如果任何输入数组可能c != b对于所有选中的元素对都是正确的,您可以假设它在您的分析中始终为真。