成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

究竟為什么,快速排序的時間復雜度是n*lg(n)?

開發 開發工具
究竟為什么,快速排序,時間復雜度是O(n*lg(n))呢?今天就和大家聊聊時間復雜度。

最煩面試官問,“為什么XX算法的時間復雜度是OO”,今后,不再懼怕這類問題。

快速排序分為這么幾步:

第一步,先做一次partition;

partition使用第一個元素t=arr[low]為哨兵,把數組分成了兩個半區:

  • 左半區比t大
  • 右半區比t小

第二步,左半區遞歸;

第三步,右半區遞歸;

偽代碼為:

  1. void quick_sort(int[]arr, int low, int high){ 
  2.          if(low== high) return; 
  3.          int i = partition(arr, low, high); 
  4.          quick_sort(arr, low, i-1); 
  5.          quick_sort(arr, i+1, high); 

為啥,快速排序,時間復雜度是O(n*lg(n))呢?

今天和大家聊聊時間復雜度。

畫外音:往下看,第三類方法很牛逼。

第一大類,簡單規則

為方便記憶,先總結幾條簡單規則,熱熱身。

規則一:“有限次操作”的時間復雜度往往是O(1)。

例子:交換兩個數a和b的值。

  1. void swap(int& a, int& b){ 
  2.          int t=a
  3.          a=b
  4.          b=t

分析:通過了一個中間變量t,進行了3次操作,交換了a和b的值,swap的時間復雜度是O(1)。

畫外音:這里的有限次操作,是指不隨數據量的增加,操作次數增加。

規則二:“for循環”的時間復雜度往往是O(n)。

例子:n個數中找到最大值。

  1. int max(int[] arr, int n){ 
  2.          int temp = -MAX; 
  3.          for(int i=0;i<n;++i) 
  4.                    if(arr[i]>temp) temp=arr[i]; 
  5.          return temp; 

分析:通過一個for循環,將數據集遍歷,每次遍歷,都只執行“有限次操作”,計算的總次數,和輸入數據量n呈線性關系。

規則三:“樹的高度”的時間復雜度往往是O(lg(n))。

分析:樹的總節點個數是n,則樹的高度是lg(n)。

在一棵包含n個元素二分查找樹上進行二分查找,其時間復雜度是O(lg(n))。

對一個包含n個元素的堆頂元素彈出后,調整成一個新的堆,其時間復雜度也是O(lg(n))。

第二大類:組合規則

通過簡單規則的時間復雜度,來求解組合規則的時間復雜度。

例如:n個數冒泡排序。

  1. void bubble_sort(int[] arr, int n){ 
  2.    for(int i=0;i<n;i++) 
  3.        for(int j=0;j<n-i-1;j++) 
  4.            if(arr[j]>arr[j+1]) 
  5.                 swap(arr[j], arr[j+1]); 

分析:冒泡排序,可以看成三個規則的組合:

  • 外層for循環
  • 內層for循環
  • 最內層的swap

故,冒泡排序的時間復雜度為:

O(n) * O(n) * O(1) = O(n^2)

又例如:TopK問題,通過建立k元素的堆,來從n個數中求解最大的k個數。

先用前k個元素生成一個小頂堆,這個小頂堆用于存儲,當前最大的k個元素。

接著,從第k+1個元素開始掃描,和堆頂(堆中最小的元素)比較,如果被掃描的元素大于堆頂,則替換堆頂的元素,并調整堆,以保證堆內的k個元素,總是當前最大的k個元素。

直到,掃描完所有n-k個元素,最終堆中的k個元素,就是為所求的TopK。

偽代碼:

  1. heap[k] = make_heap(arr[1, k]); 
  2. for(i=k+1 to n){ 
  3.          adjust_heap(heep[k],arr[i]); 
  4. return heap[k]; 

分析:可以看成三個規則的組合:

  • 新建堆
  • for循環
  • 調整堆

故,用堆求解TopK,時間復雜度為:

O(k) + O(n) * O(lg(k)) = O(n*lg(k))

畫外音:注意哪些地方用加,哪些地方用乘;哪些地方是n,哪些地方是k。

第三大類,遞歸求解

簡單規則和組合規則可以用來求解非遞歸的算法的時間復雜度。對于遞歸的算法,該怎么分析呢?

接下來,通過幾個案例,來說明如何通分析遞歸式,來分析遞歸算法的時間復雜度。

案例一:計算 1到n的和,時間復雜度分析。

如果用非遞歸的算法:

  1. int sum(int n){ 
  2.          int result=0
  3.          for(int i=0;i<n;i++) 
  4.                    result += i; 
  5.          return result; 

根據簡單規則,for循環,sum的時間復雜度是O(n)。

但如果是遞歸算法,就沒有這么直觀了:

  1. int sum(int n){ 
  2.          if (n==1) return 1; 
  3.          return n+sum(n-1); 

如何來進行時間復雜度分析呢?

用f(n)來表示數據量為n時,算法的計算次數,很容易知道:

(1) 當n=1時,sum函數只計算1次

畫外音:if (n==1) return 1;

即:

f(1)=1【式子A】

(2) 不難發現,當n不等于1時:

f(n)的計算次數,等于f(n-1)的計算次數,再加1次計算

畫外音:return n+sum(n-1);

即:

f(n)=f(n-1)+1【式子B】

【式子B】不斷的展開,再配合【式子A】:

畫外音:這一句話,是分析這個算法的關鍵。

  1. f(n)=f(n-1)+1 
  2. f(n-1)=f(n-2)+1 
  3. … 
  4. f(2)=f(1)+1 
  5. f(1)=1 

上面共n個等式,左側和右側分別相加:

  1. f(n)+f(n-1)+…+f(2)+f(1) 
  2. [f(n-1)+1]+[f(n-2)+1]+…+[f(1)+1]+[1] 

即得到:

  1. f(n)=n 

已經有那么點意思了哈,再來個復雜點的算法。

案例二:二分查找binary_search,時間復雜度分析。

  1. int BS(int[] arr, int low, int high, int target){ 
  2.          if (low>high) return -1; 
  3.          mid = (low+high)/2; 
  4.          if (arr[mid]== target) return mid; 
  5.          if (arr[mid]> target) 
  6.                   return BS(arr, low, mid-1, target); 
  7.          else 
  8.                   return BS(arr, mid+1, high, target); 

二分查找,單純從遞歸算法來分析,怎能知道其時間復雜度是O(lg(n))呢?

仍用f(n)來表示數據量為n時,算法的計算次數,很容易知道:

(1) 當n=1時,bs函數只計算1次

畫外音:不用糾結是1次還是1.5次,還是2.7次,是一個常數次。

即:

f(1)=1【式子A】

(2) 在n很大時,二分會進行一次比較,然后進行左側或者右側的遞歸,以減少一半的數據量:

f(n)的計算次數,等于f(n/2)的計算次數,再加1次計算

畫外音:計算arr[mid]>target,再減少一半數據量迭代

即:

f(n)=f(n/2)+1【式子B】

【式子B】不斷的展開,

  1. f(n)=f(n/2)+1 
  2. f(n/2)=f(n/4)+1 
  3. f(n/4)=f(n/8)+1 
  4. … 
  5. f(n/2^(m-1))=f(n/2^m)+1 

上面共m個等式,左側和右側分別相加:

  1. f(n)+f(n/2)+…+f(n/2^(m-1)) 
  2. [f(n/2)+1]+[f(n/4)+1]+…+[f(n/2^m)]+[1] 

即得到:

f(n)=f(n/2^m)+m

再配合【式子A】:

f(1)=1

即,n/2^m=1時, f(n/2^m)=1, 此時m=lg(n), 這一步,這是分析這個算法的關鍵。

將m=lg(n)帶入,得到:

f(n)=1+lg(n)

神奇不神奇?

最后,大boss,快速排序遞歸算法,時間復雜度的分析過程。

案例三:快速排序quick_sort,時間復雜度分析。

  1. void quick_sort(int[]arr, int low, inthigh){ 
  2.          if (low==high) return; 
  3.          int i = partition(arr, low, high); 
  4.          quick_sort(arr, low, i-1); 
  5.          quick_sort(arr, i+1, high); 

仍用f(n)來表示數據量為n時,算法的計算次數,很容易知道:

當n=1時,quick_sort函數只計算1次

f(1)=1【式子A】

在n很大時:

  • 第一步,先做一次partition;
  • 第二步,左半區遞歸;
  • 第三步,右半區遞歸;

即:

f(n)=n+f(n/2)+f(n/2)=n+2*f(n/2)【式子B】

畫外音:

(1)partition本質是一個for,計算次數是n;

(2)二分查找只需要遞歸一個半區,而快速排序左半區和右半區都要遞歸,這一點在分治法與減治法一章節已經詳細講述過;

【式子B】不斷的展開, 

  1. f(n)=n+2*f(n/2) 
  2. f(n/2)=n/2+2*f(n/4) 
  3. f(n/4)=n/4+2*f(n/8) 
  4. … 
  5. f(n/2^(m-1))=n/2^(m-1)+2f(n/2^m) 

上面共m個等式,逐步帶入,于是得到:

  1. f(n)=n+2*f(n/2) 
  2. =n+2*[n/2+2*f(n/4)]=2n+4*f(n/4) 
  3. =2n+4*[n/4+2*f(n/8)]=3n+8f(n/8) 
  4. =… 
  5. =m*n+2^m*f(n/2^m) 

再配合【式子A】:

f(1)=1

即,n/2^m=1時, f(n/2^m)=1, 此時m=lg(n), 這一步,這是分析這個算法的關鍵。

將m=lg(n)帶入,得到:

  1. f(n)=lg(n)*n+2^(lg(n))*f(1)=n*lg(n)+n 

故,快速排序的時間復雜度是n*lg(n)。

wacalei,有點意思哈!

畫外音:額,估計83%的同學沒有仔細看,花5分鐘細思上述過程,一定有收獲。

總結

  • for循環的時間復雜度往往是O(n)
  • 樹的高度的時間復雜度往往是O(lg(n))
  • 二分查找的時間復雜度是O(lg(n)),快速排序的時間復雜度n*(lg(n))
  • 遞歸求解,未來再問時間復雜度,通殺

知其然,知其所以然。思路比結論重要。

【本文為51CTO專欄作者“58沈劍”原創稿件,轉載請聯系原作者】

戳這里,看該作者更多好文 

 

責任編輯:趙寧寧 來源: 51CTO專欄
相關推薦

2020-09-08 15:40:58

算法快速排序堆排序

2021-10-15 09:43:12

希爾排序復雜度

2024-04-25 08:33:25

算法時間復雜度空間復雜度

2022-09-16 10:14:41

消息順序性分布式架構

2019-11-18 12:41:35

算法Python計算復雜性理論

2018-07-31 09:52:38

機器學習排序算法圖像處理

2021-01-05 10:41:42

算法時間空間

2009-07-09 10:45:16

C#基本概念復雜度遞歸與接口

2022-02-22 10:11:01

系統軟件架構

2024-05-20 09:04:29

時間復雜度代碼

2019-12-26 07:39:36

互聯網架構ip

2017-11-03 11:02:08

數據庫中間件

2021-09-17 10:44:50

算法復雜度空間

2017-12-28 11:25:51

2015-10-13 09:43:43

復雜度核心

2020-12-30 09:20:27

代碼

2014-12-10 09:23:14

2022-02-13 20:04:04

鏈表節點代碼

2021-07-20 11:38:55

算法計算機leetcode

2020-11-30 06:26:31

算法時間表示法
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久一久久| 国产精品亚洲一区二区三区在线 | avtt国产| 欧美四虎| 久久久资源 | 午夜精品久久久久久久99黑人 | 天天爱天天操 | 午夜伦理影院 | 国产精品婷婷 | 日本激情视频在线播放 | 国产精品一区二区三区免费观看 | 97av在线| 成人影院在线视频 | 精品九九 | 国产一级视频在线播放 | 欧美在线a | 欧美国产日韩在线观看成人 | 国产欧美一区二区三区久久人妖 | 龙珠z在线观看 | 一区二区在线免费观看 | 久久一 | 日韩国产中文字幕 | 91手机精品视频 | 欧美成人手机视频 | 嫩草视频在线 | 国产精品一区二区视频 | 日韩欧美在线视频 | 欧美极品视频 | 国产三区在线观看视频 | 国产精品揄拍一区二区 | 国产 欧美 日韩 一区 | 久久精品av麻豆的观看方式 | 99在线免费观看视频 | 最新91在线| 国产激情在线观看 | 综合激情网 | 精品国产1区2区3区 在线国产视频 | 午夜影视 | 久久成人精品视频 | 欧美精品三区 | 一级片在线观看视频 |