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

O(n)的算法居然超時(shí)了,此時(shí)的n究竟是多大?

開發(fā) 前端 算法
本文詳細(xì)分析了在leetcode上做題程序?yàn)槭裁磿谐瑫r(shí),以及從硬件配置上大體知道CPU的執(zhí)行速度,然后親自做一個(gè)實(shí)驗(yàn)來看看O(n)的算法,跑一秒鐘,這個(gè)n究竟是做大,最后給出不同時(shí)間復(fù)雜度,一秒內(nèi)可以運(yùn)算出來的n的大小。

[[412223]]

一些同學(xué)可能對計(jì)算機(jī)運(yùn)行的速度還沒有概念,就是感覺計(jì)算機(jī)運(yùn)行速度應(yīng)該會很快,那么在leetcode上做算法題目的時(shí)候?yàn)槭裁磿瑫r(shí)呢?

計(jì)算機(jī)究竟1s可以執(zhí)行多少次操作呢?接下來探討一下這個(gè)問題。

超時(shí)是怎么回事

大家在leetcode上練習(xí)算法的時(shí)候應(yīng)該都遇到過一種錯(cuò)誤是“超時(shí)”。

也就是說程序運(yùn)行的時(shí)間超過了規(guī)定的時(shí)間,一般OJ(online judge)的超時(shí)時(shí)間就是1s,也就是用例數(shù)據(jù)輸入后最多要1s內(nèi)得到結(jié)果,暫時(shí)還不清楚leetcode的判題規(guī)則,下文為了方便講解,暫定超時(shí)時(shí)間就是1s。

如果寫出了一個(gè)O(n)的算法 ,其實(shí)可以估算出來n是多大的時(shí)候算法的執(zhí)行時(shí)間就會超過1s了。

如果n的規(guī)模已經(jīng)足夠讓O(n)的算法運(yùn)行時(shí)間超過了1s,就應(yīng)該考慮log(n)的解法了。

從硬件配置看計(jì)算機(jī)的性能

計(jì)算機(jī)的運(yùn)算速度主要看CPU的配置,以2015年MacPro為例,CPU配置:2.7 GHz Dual-Core Intel Core i5 。

也就是 2.7 GHz 奔騰雙核,i5處理器,GHz是指什么呢,1Hz = 1/s,1Hz 是CPU的一次脈沖(可以理解為一次改變狀態(tài),也叫時(shí)鐘周期),稱之為為赫茲,那么1GHz等于多少赫茲呢

  • 1GHz(兆赫)= 1000MHz(兆赫)
  • 1MHz(兆赫)= 1百萬赫茲

所以 1GHz = 10億Hz,表示CPU可以一秒脈沖10億次(有10億個(gè)時(shí)鐘周期),這里不要簡單理解一個(gè)時(shí)鐘周期就是一次CPU運(yùn)算。

例如1 + 2 = 3,CPU要執(zhí)行四次才能完整這個(gè)操作,步驟一:把1放入寄存機(jī),步驟二:把2放入寄存器,步驟三:做加法,步驟四:保存3。

而且計(jì)算機(jī)的CPU也不會只運(yùn)行我們自己寫的程序上,同時(shí)CPU也要執(zhí)行計(jì)算機(jī)的各種進(jìn)程任務(wù)等等,我們的程序僅僅是其中的一個(gè)進(jìn)程而已。

所以我們的程序在計(jì)算機(jī)上究竟1s真正能執(zhí)行多少次操作呢?

做個(gè)測試實(shí)驗(yàn)

在寫測試程序測1s內(nèi)處理多大數(shù)量級數(shù)據(jù)的時(shí)候,有三點(diǎn)需要注意:

  • CPU執(zhí)行每條指令所需的時(shí)間實(shí)際上并不相同,例如CPU執(zhí)行加法和乘法操作的耗時(shí)實(shí)際上都是不一樣的。
  • 現(xiàn)在大多計(jì)算機(jī)系統(tǒng)的內(nèi)存管理都有緩存技術(shù),所以頻繁訪問相同地址的數(shù)據(jù)和訪問不相鄰元素所需的時(shí)間也是不同的。
  • 計(jì)算機(jī)同時(shí)運(yùn)行多個(gè)程序,每個(gè)程序里還有不同的進(jìn)程線程在搶占資源。

盡管有很多因素影響,但是還是可以對自己程序的運(yùn)行時(shí)間有一個(gè)大體的評估的。

引用算法4里面的一段話:

  • 火箭科學(xué)家需要大致知道一枚試射火箭的著陸點(diǎn)是在大海里還是在城市中;
  • 醫(yī)學(xué)研究者需要知道一次藥物測試是會殺死還是會治愈實(shí)驗(yàn)對象;

所以任何開發(fā)計(jì)算機(jī)程序員的軟件工程師都應(yīng)該能夠估計(jì)這個(gè)程序的運(yùn)行時(shí)間是一秒鐘還是一年。

這個(gè)是最基本的,所以以上誤差就不算事了。

以下以C++代碼為例:

測試硬件:2015年MacPro,CPU配置:2.7 GHz Dual-Core Intel Core i5

實(shí)現(xiàn)三個(gè)函數(shù),時(shí)間復(fù)雜度分別是 O(n) , O(n^2), O(nlogn),使用加法運(yùn)算來統(tǒng)一測試。

  1. // O(n) 
  2. void function1(long long n) { 
  3.     long long k = 0; 
  4.     for (long long i = 0; i < n; i++) { 
  5.         k++; 
  6.     } 
  1. // O(n^2) 
  2. void function2(long long n) { 
  3.     long long k = 0; 
  4.     for (long long i = 0; i < n; i++) { 
  5.         for (long j = 0; j < n; j++) { 
  6.             k++; 
  7.         } 
  8.     } 
  9.  
  1. // O(nlogn) 
  2. void function3(long long n) { 
  3.     long long k = 0; 
  4.     for (long long i = 0; i < n; i++) { 
  5.         for (long long j = 1; j < n; j = j*2) { // 注意這里j=1 
  6.             k++; 
  7.         } 
  8.     } 

來看一下這三個(gè)函數(shù)隨著n的規(guī)模變化,耗時(shí)會產(chǎn)生多大的變化,先測function1 ,就把 function2 和 function3 注釋掉

  1. int main() { 
  2.     long long n; // 數(shù)據(jù)規(guī)模 
  3.     while (1) { 
  4.         cout << "輸入n:"
  5.         cin >> n; 
  6.         milliseconds start_time = duration_cast<milliseconds >( 
  7.             system_clock::now().time_since_epoch() 
  8.         ); 
  9.         function1(n); 
  10. //        function2(n); 
  11. //        function3(n); 
  12.         milliseconds end_time = duration_cast<milliseconds >( 
  13.             system_clock::now().time_since_epoch() 
  14.         ); 
  15.         cout << "耗時(shí):" << milliseconds(end_time).count() - milliseconds(start_time).count() 
  16.             <<" ms"<< endl; 
  17.     } 

來看一下運(yùn)行的效果,如下圖:

O(n)的算法,1s內(nèi)大概計(jì)算機(jī)可以運(yùn)行 5 * (10^8)次計(jì)算,可以推測一下O(n^2) 的算法應(yīng)該1s可以處理的數(shù)量級的規(guī)模是 5 * (10^8)開根號,實(shí)驗(yàn)數(shù)據(jù)如下。 


O(n^2)的算法,1s內(nèi)大概計(jì)算機(jī)可以運(yùn)行 22500次計(jì)算,驗(yàn)證了剛剛的推測。

在推測一下O(nlogn)的話, 1s可以處理的數(shù)據(jù)規(guī)模是什么呢?

理論上應(yīng)該是比 O(n)少一個(gè)數(shù)量級,因?yàn)閘ogn的復(fù)雜度 其實(shí)是很快,看一下實(shí)驗(yàn)數(shù)據(jù)。

O(nlogn)的算法,1s內(nèi)大概計(jì)算機(jī)可以運(yùn)行 2 * (10^7)次計(jì)算,符合預(yù)期。

這是在我個(gè)人PC上測出來的數(shù)據(jù),不能說是十分精確,但數(shù)量級是差不多的,大家也可以在自己的計(jì)算機(jī)上測一下。

整體測試數(shù)據(jù)整理如下:

至于O(logn) 和O(n^3) 等等這些時(shí)間復(fù)雜度在1s內(nèi)可以處理的多大的數(shù)據(jù)規(guī)模,大家可以自己寫一寫代碼去測一下了。

完整測試代碼

  1. #include <iostream> 
  2. #include <chrono> 
  3. #include <thread> 
  4. using namespace std; 
  5. using namespace chrono; 
  6. // O(n) 
  7. void function1(long long n) { 
  8.     long long k = 0; 
  9.     for (long long i = 0; i < n; i++) { 
  10.         k++; 
  11.     } 
  12.  
  13. // O(n^2) 
  14. void function2(long long n) { 
  15.     long long k = 0; 
  16.     for (long long i = 0; i < n; i++) { 
  17.         for (long j = 0; j < n; j++) { 
  18.             k++; 
  19.         } 
  20.     } 
  21.  
  22. // O(nlogn) 
  23. void function3(long long n) { 
  24.     long long k = 0; 
  25.     for (long long i = 0; i < n; i++) { 
  26.         for (long long j = 1; j < n; j = j*2) { // 注意這里j=1 
  27.             k++; 
  28.         } 
  29.     } 
  30. int main() { 
  31.     long long n; // 數(shù)據(jù)規(guī)模 
  32.     while (1) { 
  33.         cout << "輸入n:"
  34.         cin >> n; 
  35.         milliseconds start_time = duration_cast<milliseconds >( 
  36.             system_clock::now().time_since_epoch() 
  37.         ); 
  38.         function1(n); 
  39. //        function2(n); 
  40. //        function3(n); 
  41.         milliseconds end_time = duration_cast<milliseconds >( 
  42.             system_clock::now().time_since_epoch() 
  43.         ); 
  44.         cout << "耗時(shí):" << milliseconds(end_time).count() - milliseconds(start_time).count() 
  45.             <<" ms"<< endl; 
  46.     } 

總結(jié)

本文詳細(xì)分析了在leetcode上做題程序?yàn)槭裁磿谐瑫r(shí),以及從硬件配置上大體知道CPU的執(zhí)行速度,然后親自做一個(gè)實(shí)驗(yàn)來看看O(n)的算法,跑一秒鐘,這個(gè)n究竟是做大,最后給出不同時(shí)間復(fù)雜度,一秒內(nèi)可以運(yùn)算出來的n的大小。

建議錄友們也都自己做一做實(shí)驗(yàn),測一測,看看是不是和我的測出來的結(jié)果差不多。

這樣,大家應(yīng)該對程序超時(shí)時(shí)候的數(shù)據(jù)規(guī)模有一個(gè)整體的認(rèn)識了。

 

責(zé)任編輯:姜華 來源: 代碼隨想錄
相關(guān)推薦

2019-04-26 13:55:02

Istio微服務(wù)架構(gòu)

2019-06-04 14:15:08

JavaScript V8前端

2019-07-22 15:29:53

JavaScriptGitHub語言

2011-02-28 09:51:43

內(nèi)省

2011-02-16 16:13:40

Debian

2021-03-08 21:44:33

以太坊區(qū)塊鏈比特幣

2015-08-26 09:54:19

物聯(lián)網(wǎng)

2011-08-04 13:24:28

IT運(yùn)維

2012-05-28 22:49:50

PureView

2021-02-19 20:38:01

互聯(lián)網(wǎng)衛(wèi)星系統(tǒng)

2022-06-13 09:51:35

UWB超寬帶無線載波通信技術(shù)

2020-06-11 09:18:34

動靜分離架構(gòu)架構(gòu)設(shè)計(jì)開發(fā)

2018-07-05 16:15:26

緩存數(shù)據(jù)cache miss

2010-08-24 09:19:59

2020-07-08 08:09:08

邊緣計(jì)算邊緣云云平臺

2021-08-24 10:57:24

Linux文件系統(tǒng)內(nèi)存

2025-06-25 14:18:36

LAMLAMsGUI

2021-06-11 11:34:37

臉書Facebook商業(yè)帝國

2021-08-09 05:19:08

Provider 前端前端代碼

2019-10-21 13:58:22

爬蟲互聯(lián)網(wǎng)程序員
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 欧美aaaa视频| 一区二区三 | 美女天堂在线 | 国产成人99久久亚洲综合精品 | 国产一区二区 | 天堂色网 | 欧美一区二区三区四区在线 | 久久9精品 | 亚洲成人国产 | 亚洲永久精品国产 | 3p视频在线观看 | a毛片视频网站 | 成人av电影在线 | av在线三级| 四虎影院在线播放 | 婷婷成人在线 | 成人精品国产免费网站 | 国产成人精品免费视频大全最热 | 欧美日韩久久 | 欧美久久精品 | 欧美福利精品 | 黄色一级大片在线免费看产 | 国产精品久久久久久中文字 | 午夜看电影在线观看 | 欧洲一级毛片 | av国产在线观看 | 久久亚洲春色中文字幕久久久 | 日韩av一区二区在线观看 | 中国大陆高清aⅴ毛片 | 999国产视频| 欧美日韩网站 | 久久99这里只有精品 | 日韩精品在线观看视频 | 超碰免费观看 | 亚洲成人999 | av二区三区 | 亚洲欧美另类在线观看 | 天天干干| 欧美日韩不卡合集视频 | 小h片免费观看久久久久 | 日韩av成人在线 |