摘要:以上是我對時間復雜度和空間復雜度的一些認識,有不足或者不對的地方,希望指出來
1. 博客背景
今天有同事在檢查代碼的時候,由于函數(shù)寫的性能不是很好,被打回去重構(gòu)了,細思極恐,今天和大家分享一篇用js講解的時間復雜度和空間復雜度的博客
2. 復雜度的表示方式之前有看過的,你可能會看到這么一串東西
T(n) = O(f(n)) S(n) = O(f(n))
這個叫做大O表示法,其中的T代表的是算法需要執(zhí)行的總時間
S表示的算法需要的總空間
f(n)表示的是代碼執(zhí)行的總次數(shù)
舉個例子
function go(n) { var item = 0; // 這里執(zhí)行了一次 for (var i = 0; i < n; i++) { //這里執(zhí)行了N次 for (var j = 0; j < n; j++) { //這里執(zhí)行了n*n次 item = item + i + j; //這里執(zhí)行了n*n次 } } return item; //這里執(zhí)行了一次 }
所以說上邊這段代碼是 1+n+n*n*2+1=2+n+2n2
也就是說 T(n) = O(f(2+n+2n2))
然后之前說了時間復雜度看的是一個代碼執(zhí)行的時間的趨勢, 所以說在N,也就是規(guī)模比較大的時候,那些常量是起不到?jīng)Q定性的作用的,所以這個時候我們忽略這些常量,這里的例子是一個單段的代碼,這里只看最大量級的循環(huán)就可以了
所以最后的這個代碼的時間復雜度是T(n) = O(n2)
大家可以想想一下數(shù)據(jù)中平方的曲線圖
3. 時間復雜度 3.1 時間復雜度的定義首先什么是時間復雜度,時間復雜度這個定義如果在之前沒有接觸過的話,你可能會認為他代表的是一個代碼執(zhí)行的時間,其實不然,算法的時間復雜度就是說一個算法的執(zhí)行時間根據(jù)數(shù)據(jù)規(guī)模增長的一個趨勢,并不是說代碼執(zhí)行的具體時間
3.2 幾種常見的時間復雜度最簡單的O(n)
for (var i = 0; i < n; i++) {
sum += i;
}
通俗易懂,這段代碼的執(zhí)行時間完全由N來控制,所以說T(n) = O(n)
當然還有個更簡單的O(1)
function total(n) {
console.log(1)
}
無論怎么樣,這段函數(shù)不受任何參數(shù)影響,代碼走一遍就完事,這種的代碼用T(n) = O(1) 表示
T(n) = O(n2)
上邊的例子已經(jīng)說了一個了兩層循環(huán)的那種,在舉一個時間復雜度多塊代碼的情況時間復雜度的計算方式
function go(i) { var sum = 0; for (var j = 0; j < i; j++) { sum += i; } return sum; } function main(n) { var res = 0; for (var i = 0; i < n; i++) { res = res + go(i); // 這里是重點 } }
在上邊的代碼種第二段代碼里邊調(diào)用了第一段代碼,所以說在這個代碼里邊是
go:(1+n)
在main函數(shù)里邊的時候是(1+n*go)=(1+n+n*n)
所以最后的時間復雜度是T(n) = O(n2)
3.3 多塊代碼的時間復雜度上邊距離說明的T(n) = O(n2) ,是一個函數(shù)在另一個函數(shù)里邊被調(diào)用,這種情況是被把兩個函數(shù)的時間復雜度相乘。
還有另外一種情況,就是說在一個函數(shù)里邊有多塊代碼,但是并沒有被相互調(diào)用,那么這種情況的時候,我們只需要取復雜度最大的代碼塊就可以了
比如說
function go(n) { for (var i = 0; i < n; i++) { for (var j = 0; j < n; j++) { console.log(1) } } for (var i = 0; i < n; i++) { console.log(2) } }
上邊這塊代碼中,第一塊代碼有兩層循環(huán),通過上邊的例子我們已經(jīng)得知復雜度是
n2
下邊這塊代碼,是n
那么在這種情況的時候,當N接近無限大的時候N是對n2起不到?jīng)Q定性作用的,所以上邊這塊代碼的時間復雜度就是取最大值的n2
3.4 對數(shù)階和相加情況var i = 1; while (i <= n) { i = i * 10; }
在這段代碼中,可以看到while里邊,作為判斷條件的i被每次*10,那么所以說最后循環(huán)的次數(shù)并不是n次,而是說十分之一n次,所以說這個時候的時間復雜度是10i=n,
i=logn
所以得出結(jié)論就是時間復雜度是T(n)=O(logn)
然后還有一種情況就是通過改變的變量去增加循環(huán)次數(shù)的,同理是增加了時間復雜度
還有一些其他的情況比如時間復雜度相加
function go(m,n) { for (var i = 0; i < n; i++) { console.log(1) } for (var i = 0; i < m; i++) { console.log(2) } }
請看上邊這一段,這段代碼里邊一個函數(shù)里邊有兩個循環(huán),但是形參有兩個,我們現(xiàn)在無法得知n和m到底誰大誰小,所以說這個時候代碼的時間復雜度是O(m+n)
4. 空間復雜度 4.1 空間復雜度的定義上邊說了那么一大堆的時間復雜度,相比各位已經(jīng)比較了解了,就名字來看,時間復雜度看的是代碼的執(zhí)行時間的趨勢,那么同理的,空間復雜度就是指的占用內(nèi)存的趨勢
4.2 常見的空間復雜度空間復雜度沒有時間復雜度那么復雜,常見的就那么幾種
畢竟我感覺不會有人一直循環(huán)著各種花樣的聲明變量吧。。。
如果有,那么請打死。。。。
O(1)
let a = 1; let b = 1; let c = 1; let d = 1;
很簡單,O(1)
O(n)
let arr =Array(n)
看這句代碼,代碼中創(chuàng)建了一個n長度的數(shù)組,很明顯數(shù)組的長度根據(jù)n來決定,所以說
O(n)
這里需要說明一下,這里沒有用循環(huán),是因為只要不是在循環(huán)里邊不停的聲明變量,只改變值的話是不會層架空間復雜度的
O(n2)
let arr=[] for (var i = 0; i < n; i++) { arr[i]=i for (var j = 0; j < n; j++) { arr[i][j]=j } }
怎么樣,猛的一看這個代碼是不是很刺激,我覺得如果有這種情況的話,一般都會被亂棍打死了。。。
復雜度的優(yōu)化再說優(yōu)化之前我先盜一張圖給大家看一下各個復雜度的曲線圖,方便大家有一個直觀的認識
舉個比較簡單的優(yōu)化的例子
console.time("a") function go(n) { var item = 0; for (var i = 1; i <= n; i++) { item += i; } return item; } console.timeEnd("a") console.time("b") function go2(n) { var item = n*(n+1)/2 return item; } console.timeEnd("b") go(1000) go2(1000)
大家可以打印一下看一下
希望大家原諒我數(shù)學不好,記得之前看到過一個等差數(shù)列的例子,想不到其他的性能優(yōu)化的例子
希望大家看完之后可以了解這些概念,有的時候這個東西真的很重要,找一個曲線比較高的例子
斐波那契,就是從第三項開始依次等于前兩項的和
斐波那契定義
function Fibonacci(n) { if (n <= 1 ) { return n; } else { return Fibonacci(n - 1) + Fibonacci(n - 2); } } console.time("b") Fibonacci(????) console.timeEnd("b")
有興趣的可以試試打印一下,看看時間,不過大概50次的時候你得瀏覽器就應該沒有響應了,具體請往上看曲線圖。。。。
以上是我對時間復雜度和空間復雜度的一些認識,有不足或者不對的地方,希望指出來
o(* ̄▽ ̄*)ブ
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/106364.html
摘要:今天跟大家分享多種排序算法里使用較廣泛,速度快的排序算法快速排序法平均時間復雜度為。快速排序法的原理快速排序是一種劃分交換排序,它采用分治的策略,通常稱其為分治法。 HTML5學堂-碼匠:前幾期算法之旅跟大家分享了冒泡排序法和選擇排序法,它們都屬于時間復雜度為O(n^2)的慢排序。今天跟大家分享多種排序算法里使用較廣泛,速度快的排序算法—— 快速排序法 [ 平均時間復雜度為O (n l...
摘要:數(shù)據(jù)在內(nèi)存中的存儲結(jié)構(gòu),也就是物理結(jié)構(gòu),分為兩種順序存儲結(jié)構(gòu)和鏈式存儲結(jié)構(gòu)。數(shù)組就是順序存儲結(jié)構(gòu)的典型代表。即談數(shù)據(jù)結(jié)構(gòu)又談算法才能夠真正裝爺。 什么是數(shù)據(jù)結(jié)構(gòu)概念官方定義: 數(shù)據(jù)結(jié)構(gòu)是一門研究非數(shù)值計算的程序設計問題中的操作對象,以及它們之間的關系和操作等相關問題的學科。 我的理解: 程序設計 = 數(shù)據(jù)結(jié)構(gòu) + 算法 數(shù)據(jù)結(jié)構(gòu),顧名思義,就是數(shù)據(jù)之間的結(jié)構(gòu)關系,或者理解成數(shù)據(jù)元素相互...
摘要:數(shù)據(jù)在內(nèi)存中的存儲結(jié)構(gòu),也就是物理結(jié)構(gòu),分為兩種順序存儲結(jié)構(gòu)和鏈式存儲結(jié)構(gòu)。數(shù)組就是順序存儲結(jié)構(gòu)的典型代表。即談數(shù)據(jù)結(jié)構(gòu)又談算法才能夠真正裝爺。 什么是數(shù)據(jù)結(jié)構(gòu)概念官方定義: 數(shù)據(jù)結(jié)構(gòu)是一門研究非數(shù)值計算的程序設計問題中的操作對象,以及它們之間的關系和操作等相關問題的學科。 我的理解: 程序設計 = 數(shù)據(jù)結(jié)構(gòu) + 算法 數(shù)據(jù)結(jié)構(gòu),顧名思義,就是數(shù)據(jù)之間的結(jié)構(gòu)關系,或者理解成數(shù)據(jù)元素相互...
摘要:什么是回溯算法回溯法是一種系統(tǒng)搜索問題解空間的方法。解空間定義為與數(shù)字長度相同。最后,為什么要掌握回溯法因為懂了回溯法之后筆試里的很多題就算不了,起碼成功運行到之間是沒問題的。 什么是回溯算法?回溯法是一種系統(tǒng)搜索問題解空間的方法。為了實現(xiàn)回溯,需要給問題定義一個解空間。說到底它是一種搜索算法。只是這里的搜索是在一個叫做解空間的地方搜索。而往往所謂的dfs,bfs都是在圖或者樹這種數(shù)據(jù)...
閱讀 2304·2019-08-30 15:56
閱讀 3132·2019-08-30 13:48
閱讀 1152·2019-08-30 10:52
閱讀 1528·2019-08-29 17:30
閱讀 447·2019-08-29 13:44
閱讀 3621·2019-08-29 12:53
閱讀 1140·2019-08-29 11:05
閱讀 2695·2019-08-26 13:24