有什么特点


19

有时候,仔细检查一下,很容易确定算法的时间复杂度。具有两个嵌套循环算法显然为。该探索的所有可能的组合的算法两个值中的基团是明显。N 2 N 2 NNN2N2N

但是,我不知道如何“发现”具有复杂度的算法。例如,递归mergesort实现就是一个。mergesort或其他算法的共同特征是什么,如果我正在分析的话会给我一个提示?Θ N log N Θ(NlogN)Θ(NlogN)

我敢肯定,算法具有复杂度的方法不止一种,因此任何答案都值得赞赏。顺便说一句,我正在寻求一般特征和提示,而不是严格的证明。Θ(NlogN)


6
O(logn)表示树。
Pratik Deoghare


2
@PratikDeoghare:不一定。
拉斐尔

3
@Raphael我的意思主要是!:)
Pratik Deoghare

Answers:


17

原型是一个分而治之的算法,它可以在线性时间内划分(并重新组合)工作,然后重复执行。合并排序的工作方式是:花时间将输入分为两个大致相等的部分,递归地对每个部分进行排序,然后花费时间将两个已排序的两半合并。O n Θ n Θ(nlogn)O(n)Θ(n)

直觉上,继续采用分而治之的思想,每个分割阶段总共花费线性时间,因为分割所要花费的时间是线性的,所以要分割的件数的增加恰好与零件尺寸的减小相匹配。总运行时间是一个划分阶段的总成本乘以划分阶段数的乘积。由于每次都将碎片的大小减半,因此有分割阶段,因此总运行时间为。(直到一个乘法常数,对数的底数是无关紧要的。)ñ 日志Ñ log2(n)nlog(n)

将其放在等式()中,估算这种算法的运行时间的一种方法是递归表示:。显然,此算法花费的时间比线性时间还多,我们可以通过除以来了解更多: 当翻倍时,增加一个常数:对数增加,换句话说,。T n = 2 T n / 2 + Θ n n T n T(n)T(n)=2T(n/2)+Θ(n)nnTn/nTn/nTn=Θnlogn

T(n)n=T(n/2)n/2+Θ(1)
nT(n)/nT(n)/nT(n)=Θ(nlogn)

这是更一般的模式的一个实例:母定理。对于任何递归算法,其将它的大小的输入成块尺寸的和花费时间进行拆分重组,运行时间满足。这导致取决于和的值以及的形状的闭合形式。如果并且,则主定理指出。一个Ñ / b ˚F Ñ ţ Ñ = 一个Ť ñ / b + ˚F Ñ 一个b ˚F 一个= b ˚F Ñ = Θ Ñ ţ Ñ = Θ Ñ 登录n nan/bf(n)T(n)=aT(n/b)+f(n)abfa=bf(n)=Θ(n)T(n)=Θ(nlogn)


1
总结一下:一次消除搜索空间恒定部分的算法将显示对数项。其他因素取决于执行清除的时间。
拉斐尔

1
示例:快速排序平均情况O(nlogn)
vzn

11

另外两种需要时间的算法:Θ(nlogn)

依次处理每个项目并且需要对数时间来处理每个项目的算法(例如HeapSort或许多平面扫描计算几何算法)。

运行时间主要由排序预处理步骤决定的算法。(例如,在最小生成树的Kruskal算法中,第一步可以按权重对边缘进行排序)。


赞成第一段。第二个似乎是多余的,因为我们知道的线性排序算法是分而治之或堆排序。第一个类别的示例是在大小为n的二叉搜索树(或排序数组)中搜索对象;在更抽象的层面上,这也可以看作是分而治之。nn
拉斐尔

@Raphael我知道排序与已经给出的运行时间类别是多余的。关键是排序有时是“瓶颈”,而乍一看不是排序问题的算法可能仍然具有运行时的运行时间,因为排序是必需的。

9

另一类:输出的大小为,因此Θ n log n )的运行时间在输出大小中线性的。Θ(nlogn)Θ(nlogn)

尽管此类算法的细节通常使用分而治之的技术,但不一定必须如此。运行时间从根本上取决于所提问题,因此我认为值得一提。

这出现在基于增强型二进制搜索树的数据结构中,其中每个节点存储一个线性大小的数据结构,以搜索该节点的子树中的叶子。这种数据结构经常出现在几何范围搜索中,并且通常基于分解方案。请参阅Agarwal的调查

对于一个具体示例,请考虑range-tree,它是为回答二维正交范围查询而构建的。尽管后来使用某些压缩技术将多个对象打包成一个单词来减少了空间,但是数据结构的教科书(也是最直观的)版本需要空间(每个叶子在每个位置存储在一个辅助结构中)从叶到根的路径上的节点,或在O log n 位置),构造算法在空间需求中采用线性时间。O(nlogn)O(logn)


一个例子是用筛子找到的第n个素数,因为你需要大小的筛子θ(nlogn)
gnasher729


5

这些通常是“分而治之”类型的算法,其中划分和合并子解决方案的成本不会“太大”。请查看此常见问题解答,以了解哪些类型的重复出现会导致这种行为。



-1

O(nlogn)

for (i = 0; i < constant; i++){
    for(j = 0; j < n; j++){
        // Do some O(1) stuff on the input
    }
}

// Alternative Variant:
for (i = 0; i < constant; i++){
    for(j = n; j < constant; j++){
        // Do some O(1) stuff on the input
    }
}

O(n2)

我无法给出使用此循环的算法的具体示例,但是在编写自定义算法时经常会出现这种情况。


O(nlogn)Θ(n)Θ(1)Θ(|n|)n

O(nlogn)

另外,最初的问题并没有要求大θ。
Nicolas Miari 2014年

1
O(nlogn)O(22n)O(almost anything else)Θ(nlogn)O(nlogn)
David Richerby 2014年

O(nlogn)O(nlogn)O(nlogn)O(nlogn)
Nicolas Miari 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.