极客时间课程《数据结构与算法之美》01 - 复杂度

复杂度计算

O (logn)

i=1;
 while (i <= n)  {
   i = i * 2;
 }

实际效果:java

2^{0} *  2^{1} *  2^{2} ···  2^{k} ··· 2^{x}= n

经过 2x=n 求解 x 。
x=log2n,因此,这段代码的时间复杂度就是O (log2n)。数组

无论底数是几,全部对数阶的时间复杂度都记为
O (logn)。由于
O (log3n) = O(C * log2n),使用大O标记复杂度的时候,能够忽略系数,因此赞成表示为O (logn)。数据结构

好比,归并排序、快速排序的时间复杂度都是 O (nlogn)。code

O(m+n)、O(m*n)
代码复杂度由两个数据的规模来决定。

int cal(int m, int n) {
  int sum_1 = 0;
  int i = 1;
  for (; i < m; ++i) {
    sum_1 = sum_1 + i;
  }

  int sum_2 = 0;
  int j = 1;
  for (; j < n; ++j) {
    sum_2 = sum_2 + j;
  }

  return sum_1 + sum_2;
}

其中m和n是表示两个数据规模,没法事先评估m和n哪一个大,因此不能随意省略,故,上面代码的时间复杂度就是 O (m+n)。排序

空间复杂度

void print(int n) {
  int i = 0;
  int [ ] a = new int[n];
  for (i; i <n; ++i) {
    a[i] = i * i;
  }

  for (i = n-1; i >= 0; --i) {
    print out a[i]
  }
}

第2行申请一个空间存储变量i,能够忽略,和n无关。
第三行申请了大小为n的int类型数组,除此以外,无更多空间占用。故复杂度为O(n)。class

均摊时间复杂度

大部分状况下,没必要区分最好、最坏、平均状况时间复杂度三种状况。变量

// array 表示一个长度为 n 的数组
 // 代码中的 array.length 就等于 n
 //这段代码仅仅是王争给的例子,没什么特殊实际意义。
 int[] array = new int[n];
 int count = 0;
 
 void insert(int val) {
    if (count == array.length) {
       int sum = 0;
       for (int i = 0; i < array.length; ++i) {
          sum = sum + array[i];
       }
       array[0] = sum;
       count = 1;
    }

    array[count] = val;
    ++count;
 }

咱们仍是继续看在数组中插入数据的这个例子。每一次 O (n) 的插入操做,都会跟着 n-1 次 O (1) 的插入操做,因此把耗时多的那次操做均摊到接下来的 n-1 次耗时少的操做上,均摊下来,这一组连续的操做的均摊时间复杂度就是 O (1)。这就是均摊分析的大体思路。方法

对一个数据结构进行一组连续操做中,大部分状况下时间复杂度都很低,只有个别状况下时间复杂度比较高,并且这些操做之间存在先后连贯的时序关系,这个时候,咱们就能够将这一组操做放在一起分析,看是否能将较高时间复杂度那次操做的耗时,平摊到其余那些时间复杂度比较低的操做上。并且,在可以应用均摊时间复杂度分析的场合,通常均摊时间复杂度就等于最好状况时间复杂度。数据

均摊时间复杂度就是一种特殊的平均时间复杂度,不必花太多精力去区分它们。最应该掌握的是它的分析方法,摊还分析。至于分析出来的结果是叫平均仍是叫均摊,这只是个说法,并不重要。时间

新知

对于可反复读写的存储空间,认为它空即为空。清空数组有时候并不须要置为0,或某个值。把下标指到第一个位置就能够。

留言体会:平均和平摊基本就是一个概念,平摊是特殊的平均。在分析时间复杂度是 O (1) 仍是 O (n) 的时候最简单就是凭感受,,,,,,,,出现 O (1) 的次数远大于出现 O (n) 出现的次数,那么平均平摊时间复杂度就是 O (1)。。。。

相关文章
相关标签/搜索