【发布时间】:2011-10-12 21:44:15
【问题描述】:
我知道什么是 O(n) 表示法,并且我也了解如何获得 O(n)、O(n2)、...等表示法。
- O(n) 意味着我必须通过序列一次
- O(n2) 表示我有两个嵌套循环遍历序列
但是我如何获得 log(N)?
P.S.:我知道 Collections API 和一些具有 O(n log n) 遍历时间的类。我需要一个简单的解释。
【问题讨论】:
标签: algorithm programming-languages big-o
我知道什么是 O(n) 表示法,并且我也了解如何获得 O(n)、O(n2)、...等表示法。
但是我如何获得 log(N)?
P.S.:我知道 Collections API 和一些具有 O(n log n) 遍历时间的类。我需要一个简单的解释。
【问题讨论】:
标签: algorithm programming-languages big-o
lg N 出现在分治算法中,您可以迭代或递归地跳过 N 个项目集合中的一半数据。 Binary search 是典型的例子。二叉搜索树的插入、查找和删除操作也是O(lg N)。
迭代地丢弃一半的元素,从直觉上看,是迭代地加倍元素数量的逆过程。加倍会在 N 次迭代中产生 O(2^N) 个元素。请注意,N 的二进制对数是 2 次幂 N 的倒数。
可以通过合并排序等算法在 O(N lg N) 中对数组进行排序,但在概念上也更简单:遍历数组并将元素放入二叉搜索树。每个插入需要 O(lg N) 并且有 N 个,因此算法运行在 O(N lg N)。
(如果树是balanced,则按 BST 排序甚至具有最坏情况 O(N lg N) 复杂度。)
【讨论】:
我认为最好的例子 N*log(N) 是查看基于比较的搜索:
我们以merge-sort 为例。
该算法采用一个元素数组,递归地将其拆分为 2,直到它得到一个长度为 2 的数组,然后在 O(n) 处合并这些片段,每个合并排序数组更容易。
好的,这是一个简单的描述,现在让我们看看它是什么样子的:
[ 1 2 3 4 5 6 7 8 ]
|
/\
[1 2 3 4] [ 5 6 7 8 ]
| |
/\ /\
[1 2 ] [ 3 4] [5 6] [7 8]
我希望你能在这里看到,递归的 深度 是 log(n)(因为它是一棵有 2 个分支的树……所以它是 log(n),基数为 2 )
但是在树的每个 level 中都有 O(n) 次操作(因为我们正在积极地重新排列 n 个对象)。
所以这里有 N*log(N) 复杂度。
大多数具有 Log(N) 复杂度的算法都是从基于树的算法中获得的。
有一些只是概率 log(n)(这意味着经过长时间的数学计算后,您会得到平均而言,它会类似于 log(n))
【讨论】:
复杂度为 O(log n) 的典型算法是在有序数组中进行二分查找。而不是逐个遍历每个元素 O(n) 您迭代地将数组分成两半,并且只查看您知道元素可以存在的那一半。
【讨论】: