算法向|大O小析

大O定义(Big O notation)


描述算法所用时间随着输入变量变化的时间增长关系(这里是非严谨的定义,如果需要数学严谨性的定义,请参考《算法概论》里面的定义。

 

就是给了一个输入N,时间会随着N怎么变化,这个N是输入参数,O(N)和O(x)或者O(y)没有区别。这里的时间会随着CPU等硬件而不同,这里我们其实强调的是算法的步骤,来代替实际的时间。

 

其实O(N)表示最坏的情况下用的时间,Ω(N)表示最好的情况下用的时间。θ(N)表示平均时间。这里只讨论O(N)

大O的计算原则

1.常量是被忽略的,如14n² ,直接变成n²

2.忽略低次幂,如n²+n,直接变成n²。因为n²+n <= n²+n²<=2n² ,根据第一条,常数忽略为n² 

3.n在指数位置,则忽略n的底数位置。如3n+n5,则忽略n5,直接变成3n

4.n的多项式,则忽略n的对数,如n+(logn)3 直接写成n

 这样我们就关注算法的重要影响部分。

时间复杂度举例

1. 斐波那契数列,伪代码

function fib1(n)
if n = 0: return 0
if n = 1: return 1
return fib1(n - 1) + fib1(n - 2)

 

分析:对于n<=1,时间复杂度为O(1),对于n>1 ,用时有O(n) = O(n-1)+O(n-2)[二阶齐次差分方程,具体百度] =O(2n),可以看出,递归还是很耗时的。因为他每一次都是往下分了2个调用,时间是2×2×2...如下图:

 

 

2.冒泡排序

 

function bubble_sort (array, n) {
var i, j;
for(i from 0 to n-1){
for(j from 0 to n-1-i){
if (array[j] > array[j+1])
swap(array[j], array[j+1])}}
}

 

 分析:外层是n,内层是(n-1+n-2+n-3+...+3+2+1),所以是n*(n/2)=O(n²/2),忽略常数1/2,记作O(n²).当然这是最坏的情况,最好的情况是O(n),加个flag,标识是否交换,没有交换直接结束了。

3.二分查找

 BinarySearch_Left(A[0..N-1], value) {
      low = 0
      high = N - 1
      while (low <= high) {
          // invariants: value > A[i] for all i < low
                         value <= A[i] for all i > high
          mid = (low + high) / 2
          if (A[mid] >= value)
              high = mid - 1
          else
              low = mid + 1
      }
      return low
  }

分析:查找的次数---经过多少次(除以二)最后数字变成1,设经过x次,有:1 = N / 2x,则x=log2 N,所以算法复杂度是O(log2 N).

 

End

 

posted @ 2018-01-01 22:31  IT圈圈  阅读(358)  评论(0编辑  收藏  举报

皮皮虾美剧