數據結構與算法之美學習筆記:第四講

1、複雜度分析的4個概念

// n 表示數組 array 的長度
int find(int[] array, int n, int x) {
  int i = 0;
  int pos = -1;
  for (; i < n; ++i) {
    if (array[i] == x) {
       pos = i;
       break;
    }
  }
  return pos;
}

1.最壞狀況時間複雜度:代碼在最理想狀況下執行的時間複雜度。

  要查找的變量 x 正好是數組的第一個元素java

2.最好狀況時間複雜度:代碼在最壞狀況下執行的時間複雜度。

  若是數組中沒有要查找的變量 x,咱們須要把整個數組都遍歷一遍python

3.平均時間複雜度:用代碼在全部狀況下執行的次數的加權平均值表示。

  咱們把每種狀況下,查找須要遍歷的元素個數累加起來,而後再除以n+1,就能夠獲得須要遍歷的元素個數的平均值,即:算法

咱們知道,要查找的變量 x,要麼在數組裏,要麼就不在數組裏。這兩種狀況對應的機率統計起來很麻煩,爲了方便你理解
咱們假設在數組中與不在數組中的機率都爲1/2。另外,要查找的數據出如今 0~n-1 這n個位置的機率與時同樣的,爲1/n。因此,根據機率乘法法則,要查找的數據出如今 0~n0~n-1 中任意位置的機率就是 1/(2n)。編程

所以,前面的推導過程當中存在的最大問題就是,沒有將各類狀況發生的機率考慮進去,若是咱們把每種狀況發生的機率也考慮進來
那麼平均時間複雜度的計算過程變成了這樣:數組

這個值就是機率論中的加權平均值,也叫作指望值,因此平均時間複雜度的全程也叫加權平均時間複雜度或者指望時間複雜度數據結構

2、均攤時間複雜度:

 平均複雜度只在某些特殊狀況下才會用到,而均攤時間複雜度應用場景它比較特殊、更加有限有限數據結構和算法

 // 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;
 }

我先來解釋一下這段代碼

一、這段代碼實現了一個往數組中插入數據的功能。
二、當數組滿了以後也就是代碼中的 count == array.length時,咱們用for循環遍歷數組求和,並清空數組,將求和以後的sum值放到數組的第一個位置
三、而後再將新的數據插入。但若是數組一開始就有空閒空間,則直接將數據插入數組函數

最理想的狀況下,數組中有空閒的空間,咱們只須要將數據插入到數組小表爲count的位置就能夠了 複雜度爲O(1)
最壞的狀況下:數組中沒有空閒空間;額,咱們須要先作一次數組的遍歷求和,而後再將數據插入,因此最壞狀況時間複雜度爲 O(1)學習

平均時間複雜度是:O(1)

假設數組的長度是 n,根據數據插入的位置的不一樣,咱們能夠分爲n種狀況
每種狀況的時間複雜度是 O(1)。除此以外,還有一種「額外」的狀況,就是在數組沒有空閒空間時插入一個數據,這個時候的時間複雜
度是 O(n)。並且,這 n+1 種狀況發生的機率同樣都是 1/(n+1)。因此,根據加權平均的計算方法,咱們求得得的平均時間複雜度就是:spa

在代碼執行的全部複雜度狀況中絕大部分是低級別的複雜度,個別狀況是高級別複雜度且發生具備時序關係時,能夠將個別高級別複雜度均攤到低級別複雜度上。基本上均攤結果就等於低級別複雜度。

均攤時間複雜度就是一種特殊的平均時間複雜度

3、幾個爲何?

一、爲何要引入這4個概念?

1.同一段代碼在不一樣狀況下時間複雜度會出現量級差別,爲了更全面,更準確的描述代碼的時間複雜度,因此引入這4個概念。

2.代碼複雜度在不一樣狀況下出現量級差異時才須要區別這四種複雜度。大多數狀況下,是不須要區別分析它們的。

二、用生活中的例子解釋這四個概念

今天你準備去老王家拜訪下,惋惜老王的愛人叫他去打個醬油,她告訴你說她限時n分鐘🕒給他去買。那麼你想着以他家到樓下小賣部來回最多一分鐘,

最好的狀況

那麼 「最好的狀況」就是你只用等他一分鐘。

最壞的狀況:

那麼也有可能遇到突發狀況,好比說電梯人多吖,路上摔了一膠,天知道他去幹了什麼,用了n分鐘,沒辦法👐,主上有令,n分鐘限時,那這就是「最壞的狀況」。

平均時間複雜度:

難點,平均時間複雜度 就是他有多是第1.2.3...n,中的某個分鐘回來,那平均就是1+2+3+...n/n,把全部可能出現的狀況的時間複雜度相加除以狀況數 。

均攤時間複雜度:

均攤的話就是把花時間多的分給花時間少的,獲得一箇中間值,因此說這就會和平均混淆,我的以爲主要仍是概念不一樣。假如n是10分鐘,那麼9分鐘分4分鐘到1分鐘那,8分3給2...,那均攤下來就是5分鐘.

三、如何分析平均、均攤時間複雜度?

1.平均時間複雜度

代碼在不一樣狀況下複雜度出現量級差異,則用代碼全部可能狀況下執行次數的加權平均值表示。

2.均攤時間複雜度

兩個條件知足時使用:

1)代碼在絕大多數狀況下是低級別複雜度,只有極少數狀況是高級別複雜度;

2)低級別和高級別複雜度出現具備時序規律。均攤結果通常都等於低級別複雜度。

4、課後思考題

一、題目

咱們今天學的幾個複雜度分析方法,你都掌握了嗎?你能夠用今天學習的知識,來分析一下下面這個 add() 函數的時間複雜度。

// 全局變量,大小爲 10 的數組 array,長度 len,下標 i。
int array[] = new int[10]; 
int len = 10;
int i = 0;

// 往數組中添加一個元素
void add(int element) {
   if (i >= len) { // 數組空間不夠了
     // 從新申請一個 2 倍大小的數組空間
     int new_array[] = new int[len*2];
     // 把原來 array 數組中的數據依次 copy 到 new_array
     for (int j = 0; j < len; ++j) {
       new_array[j] = array[j];
     }
     // new_array 複製給 array,array 如今大小就是 2 倍 len 了
     array = new_array;
     len = 2 * len;
   }
   // 將 element 放到下標爲 i 的位置,下標 i 加一
   array[i] = element;
   ++i;
}

二、經典留言

1. 最好狀況時間複雜度爲 O(1)

2.最壞狀況分析:

最壞狀況代碼執行的次數跟每次數組的長度有關
第1次調用insert的執行的次數爲 n ,
第2次調用insert的執行的次數爲 2n ,
第3次調用insert的執行的次數爲 2^2 * n
第k次調用insert的執行的次數爲 2^(k-1) * n
最壞時間複雜度爲 O(n)。

3. 平均狀況分析
當每次遇到最壞狀況時數組會進行2倍擴容,原數組被導入新數組,雖然數組的長度變大了,可是插入操做落在的區間的長度是同樣的,分別是0~len-1, len~(2len-1),....;
插入的狀況還是len+1種:0~len-1和插滿以後的O(len);因此每次插入的機率是:p= 1/len+1,
最後求出加權平均時間複雜度爲 1*p + 2*p+ ▪▪▪ + len*p + len * p = O(1) ;

4. 均攤時間複雜度 O(1)

而均攤複雜度因爲每次O(len)的出現都跟着len次O(1),是先後連貫的,於是將O(len)平攤到前len次上,得出平攤複雜度是O(1)

三、初學者如何學

報告老師,我好像走錯了教室。

我是一個文科轉行過來的菜鳥,剛剛學完Python,基本搞懂了「遍歷」、「循環」、「判斷」等概念。
您開篇講的課,我都基本都能明白,也提起了興趣和信心,準備好好跟您學習。但這兩次課聽完,我又暈菜了。
想請問一下,若是聽不太懂(也能夠去掉「太」),須要補哪些課?您能告訴我進入您課程的坡道和墊腳石麼?有沒有稍低一點年級的資料,讓我能夠補補課呢?
還請抽時間回答,謝謝


一、你說了剛學完python,可能代碼還沒寫熟練,因此我建議把python書上的全部實例代碼都本身敲一遍,默寫一遍。學編程,光看不寫確定是不行的。

二、等你python代碼寫熟練了,你能夠再開始學我這個專欄。 由於你沒有數據結構和算法的基礎,因此我建議,配合着《大話數據結構》《算法圖解》兩本書一塊來學習。

三、學習這個專欄的過程當中,你能夠把我講到的數據結構和算法都用python代碼實現一遍,若是實現不了,能夠參照我放在Github上的代碼,本身看懂以後,默寫一遍。這個步驟很是鍛鍊你的編程能力,不要忽視!

四、在學習專欄的過程當中,不要一以爲看不懂就放棄,師傅領進門,修行靠我的。這裏沒有葵花寶典同樣的捷徑。學習還要靠本身。看不懂?那就本身多百度一下,看不懂也能夠問問你同窗、同事、學長,用一個星期來看一篇文章,狠下心來,別怕麻煩,不會學不會的。

還有不少時候看不懂,你就硬着頭皮看,都看完一遍,就會有感受。以後再等有空了,再來看一遍,慢慢的都懂了。這門課很難,對於初學者來講,應該是計算機裏最難的之一了,因此不要指望輕鬆就學會,這是不現實的。

相關文章
相關標籤/搜索