成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

【javascript系列】時(shí)間復(fù)雜度和空間復(fù)雜度

dcr309duan / 826人閱讀

摘要:第三段,時(shí)間復(fù)雜度。五空間復(fù)雜度分析空間復(fù)雜度的話和時(shí)間復(fù)雜度類似推算。

一、前言

時(shí)間復(fù)雜度和空間復(fù)雜度,我們?cè)诖髮W(xué)里的算法與數(shù)據(jù)結(jié)構(gòu)課程中已經(jīng)學(xué)習(xí)過,這回根據(jù)項(xiàng)目工作中整理一下,這個(gè)估計(jì)只是一個(gè)粗略的估計(jì)分析,并不是一個(gè)準(zhǔn)確的估計(jì)分析。

1、學(xué)習(xí)時(shí)間復(fù)雜度和空間復(fù)雜度是很有必要的,這個(gè)屬于算法與數(shù)據(jù)結(jié)構(gòu)的范疇,學(xué)這個(gè)是為了解決代碼中的“快”和“省”的問題。這樣才能使你的代碼運(yùn)行效率更高,占用空間更小。代碼執(zhí)行效率需要通過復(fù)雜度分析。

2、數(shù)據(jù)規(guī)模的大小會(huì)影響到復(fù)雜度分析。比如排序,如果是一個(gè)有序的數(shù)組,執(zhí)行效率會(huì)更高;如果數(shù)據(jù)量很少的時(shí)候,這個(gè)算法看不出性能上差別。

3、比如說不同物理機(jī)環(huán)境不一樣,比如i3,i5,i7的cpu等等,運(yùn)行內(nèi)存1G,2G,4G,8G等等;時(shí)間上肯定有差別。

二、大O的復(fù)雜度

我們來看個(gè)簡(jiǎn)單的例子,一個(gè)循環(huán)累加器。

function total(n) { 
      var sum = 0;   //t
      for (var i = 0; i < n; i++) {   // nt
        sum += i;   //nt
      } 
      return sum;  // t
    } 

分析:假設(shè)每一行代碼執(zhí)行耗時(shí)都一樣,為t,這樣整個(gè)代碼總執(zhí)行時(shí)間為(t+nt+nt+t)=(2n+2)t。

我們?cè)賮砜匆粋€(gè)栗子:

function total(n) { 
      var sum = 0;      // t
      for (var i = 0; i < n; i++) {   //nt
        for (var j = 0; j < n; j++) {     //n*n*t
          sum = sum + i + j;     //n*n*t
        }
      }
      return sum;      //t
    }

分析:假設(shè)每一行代碼執(zhí)行耗時(shí)都一樣,為t,這樣整個(gè)代碼總執(zhí)行時(shí)間為(t+nt+nnt2+t)=(2nn+n+2)t。

從數(shù)學(xué)角度來看,我們可以得出個(gè)規(guī)律:代碼的總執(zhí)行時(shí)間 T(n) 與每行代碼的執(zhí)行次數(shù)成正比.

所以上邊兩個(gè)函數(shù)的執(zhí)行時(shí)間可以標(biāo)記為 T(n) = O(2n+2) 和 T(n) = O(2n*n+n+2)。這就是大 O 時(shí)間復(fù)雜度表示法,它不代表代碼真正的執(zhí)行時(shí)間,而是表示代碼隨數(shù)據(jù)規(guī)模增長(zhǎng)的變化趨勢(shì),簡(jiǎn)稱時(shí)間復(fù)雜度。

而且當(dāng) n 很大時(shí),我們可以忽略常數(shù)項(xiàng),只保留一個(gè)最大量級(jí)即可。所以上邊的代碼執(zhí)行時(shí)間可以簡(jiǎn)單標(biāo)記為 T(n) = O(n) 和 T(n) = O(n2)。

三、時(shí)間復(fù)雜度分析 1、循環(huán)次數(shù)最多的代碼塊

在分析的時(shí)候,只需要關(guān)心哪個(gè)代碼塊循環(huán)次數(shù)最多的那段代碼,比如說剛才的第一個(gè)例子,循環(huán)最多的代碼塊是這兩行,循環(huán)都是n次。

for (var i = 0; i < n; i++){
    sum += i;
}

執(zhí)行了n次,所以事件復(fù)雜度就是O(n)。

2、最大值原則:總復(fù)雜度等于最大的代碼塊的復(fù)雜度
function total(n) { 
      // 第一個(gè) for 循環(huán)
      var sum1 = 0; 
      for (var i = 0; i < n; i++) {
        for (var j = 0; j < n; j++) {
          sum1 = sum1 + i + j; 
        }
      }
      // 第二個(gè) for 循環(huán)
      var sum2 = 0;
      for(var i=0;i<1000;i++) {
        sum2 = sum2 + i;
      }
      // 第三個(gè) for 循環(huán)
      var sum3 = 0;
      for (var i = 0; i < n; i++) {
        sum3 = sum3 + i;
      }
      return {sum1:sum1, sum2: sum2, sum3:sum3}
    }

分別分析每一段循環(huán)時(shí)間復(fù)雜度,取他們最大的量級(jí)決定整段代碼復(fù)雜度。

第一段,時(shí)間復(fù)雜度 O(n2)。

第二段,時(shí)間復(fù)雜度可以忽略,循環(huán)執(zhí)行了 1000 次,是個(gè)常數(shù)量級(jí),盡管對(duì)代碼的執(zhí)行時(shí)間會(huì)有影響,但是當(dāng) n 無限大的時(shí)候,就可以忽略。

第三段,時(shí)間復(fù)雜度O(n)。

綜上所述,所以上述代碼的時(shí)間復(fù)雜度為 O(n2)。

3、乘法原則:嵌套代碼復(fù)雜度等于嵌套內(nèi)外代碼復(fù)雜度乘積

舉個(gè)例子:

 function f(i) {
      var sum = 0;
      for (var j = 0; j < i; j++) {
        sum += i;
      }
      return sum;
    }
    function total(n) {
      var res = 0;
      for (var i = 0; i < n; i++) {
        res = res + f(i); // 調(diào)用 f 函數(shù)
      }
    }

分析一下:total方法時(shí)間復(fù)雜度O(n),f方法的時(shí)間復(fù)雜度O(n)。

所以整段代碼的時(shí)間復(fù)雜度O(n2)。

四、常見的時(shí)間復(fù)雜度分析

最高量級(jí)的復(fù)雜度,效率是遞減的

如上圖可以粗略的分為兩類,多項(xiàng)式量級(jí)和非多項(xiàng)式量級(jí)。其中,非多項(xiàng)式量級(jí)只有兩個(gè):O(2n) 和 O(n!) 對(duì)應(yīng)的增長(zhǎng)率如下圖所示

當(dāng)數(shù)據(jù)規(guī)模 n 增長(zhǎng)時(shí),非多項(xiàng)式量級(jí)的執(zhí)行時(shí)間就會(huì)急劇增加,所以,非多項(xiàng)式量級(jí)的代碼算法是非常低效的算法。

1、常數(shù)階復(fù)雜度O(1)

O(1) 只是常量級(jí)時(shí)間復(fù)雜度表示法,并不是代碼只有一行,舉個(gè)例子:

function total() {
      var sum = 0;
      for(var i=0;i<100;i++) {
        sum += i;
      }
      return sum;
    }

雖然有這么多行,即使 for 循環(huán)執(zhí)行了 100 次,但是代碼的執(zhí)行時(shí)間不隨 n 的增大而增長(zhǎng),所以這樣的代碼復(fù)雜度就為 O(1)。

2、對(duì)數(shù)階O(logn)和O(nlogn)

(1)對(duì)數(shù)階時(shí)間復(fù)雜度的常見代碼如下:

 function total1(n) {
      var sum = 0;
      var i = 1;
      while (i <= n) {
        sum += i;
        i = i * 2;
      }
    }
    function total2(n) {
      var sum = 0;
      for (var i = 1; i <= n; i = i * 2) {
        sum += i;
      }
    }

上面函數(shù)total1和total2有一個(gè)相同點(diǎn):變量 i 從 1 開始取值,每循環(huán)一次乘以 2,當(dāng)大于 n 時(shí),循環(huán)結(jié)束。

所以真正循環(huán)了x次。2x =n;,所以 x = log2n。

所以上面兩個(gè)函數(shù)時(shí)間復(fù)雜度都是 O(log2n)。

(2)我們?cè)谂e個(gè)例子:

 function total1(n) {
      var sum = 0;
      var i = 1;
      while (i <= n) {
        sum += i;
        i = i * 3;
      }
    }
    function total2(n) {
      var sum = 0;
      for (var i = 1; i <= n; i = i * 3) {
        sum += i;
      }
    }

同理可知:這兩個(gè)函數(shù)的時(shí)間復(fù)雜度為 O(log3n) 。

由于我們可以忽略常數(shù),也可以忽略對(duì)數(shù)中的底數(shù),所以在對(duì)數(shù)階復(fù)雜度中,統(tǒng)一表示為 O(logn);那 O(nlogn) 的含義就很明確了,時(shí)間復(fù)雜度 為O(logn) 的代碼執(zhí)行了 n 次。

3、其他復(fù)雜度O(m+n)和O(m*n)

舉個(gè)例子:

 function total(m,n) {
      var sum1 = 0;
      for (var i = 0; i < n; i++) {
        sum1 += i;
      }
      var sum2 = 0;
      for (var i = 0; i < m; i++) {
        sum2 += i;
      }
      return sum1 + sum2;
    }

因?yàn)槲覀儫o法評(píng)估 m 和 n 誰的量級(jí)比較大,所以就不能忽略掉其中一個(gè),這個(gè)函數(shù)的復(fù)雜度是有兩個(gè)數(shù)據(jù)的量級(jí)來決定的,所以此函數(shù)的時(shí)間復(fù)雜度為 O(m+n);那么 O(m*n) 的時(shí)間復(fù)雜度類似。

五、空間復(fù)雜度分析

空間復(fù)雜度的話和時(shí)間復(fù)雜度類似推算。 所謂空間復(fù)雜度就是表示算法的存儲(chǔ)空間和數(shù)據(jù)規(guī)模之間的關(guān)系。

舉個(gè)例子:

function initArr(n) {
      var arr = [];
      for (var i = 0; i < n; i++) {
        arr[i] = i;
      }
    }

時(shí)間復(fù)雜度的推算,忽略掉常數(shù)量級(jí),每次數(shù)組賦值都會(huì)申請(qǐng)一個(gè)空間存儲(chǔ)變量,所以此函數(shù)的空間復(fù)雜度為 O(n)。

常見的空間復(fù)雜度只有 O(1)、O(n)、O(n2)。其他的話很少會(huì)用到。

六、復(fù)雜度優(yōu)化
function total(n) {
      var sum = 0;
      for (var i = 1; i <= n; i++) {
        sum += i;
      }
      return sum;
    }

這段代碼我們很容易知道時(shí)間復(fù)雜度 O(n)。

但是我想把復(fù)雜度降一降,降低到常數(shù)階O(1)。

其實(shí)求和怎么求呢?等比數(shù)列,直接用公式,這就說明了數(shù)學(xué)好的人,算法應(yīng)該高level點(diǎn)。

function total(n) {
      var sum = n*(n+1)/2
      return sum;
    }

上面函數(shù)的時(shí)間復(fù)雜度僅僅為 O(1),在數(shù)據(jù)規(guī)模比較龐大的時(shí)候,下面的函數(shù)是不是明顯比上面的函數(shù)運(yùn)算效率更高呢。

七、總結(jié)

分析算法執(zhí)行效率與數(shù)據(jù)規(guī)模之間的增長(zhǎng)關(guān)系,可以粗略的表示,越高階復(fù)雜度的算法,執(zhí)行效率越低。

復(fù)雜度學(xué)習(xí)之后,有時(shí)候可以避免寫出效率低的代碼。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/105934.html

相關(guān)文章

  • 算法系列——JavaScript中廣度優(yōu)先搜索思想實(shí)現(xiàn)

    摘要:散列表上面的地圖向我們展示了如何用廣度優(yōu)先搜索的思想找到北京到廣州的最短路線。在廣度優(yōu)先搜索中,我們需要用到隊(duì)列的這種思想來實(shí)現(xiàn)查找。建立了下面這個(gè)模型武漢廣州西藏上海上海武漢廣州代碼完整實(shí)現(xiàn),利用遞歸和廣度優(yōu)先搜索的思想實(shí)現(xiàn)。 什么是廣度優(yōu)先搜索? 如果只是是背概念,幼兒園的小朋友都能背下來念給你聽。 假設(shè)看這篇文章的都和我一樣是個(gè)前端工程師,我們要從廣度優(yōu)先搜索(BFS)中學(xué)到什么...

    everfly 評(píng)論0 收藏0
  • javascript 數(shù)據(jù)結(jié)構(gòu)系列

    摘要:也就是說,它通過計(jì)算一個(gè)關(guān)于鍵值的函數(shù),將所需查詢的數(shù)據(jù)映射到表中一個(gè)位置來訪問記錄,這加快了查找速度。這個(gè)映射函數(shù)稱做散列函數(shù),存放記錄的數(shù)組稱做散列表。如果對(duì)象沒有該實(shí)例化該處為一對(duì)象如果該不存在就增加一個(gè)數(shù)量 本系列一系列文章的收集關(guān)于javascript中的數(shù)據(jù)結(jié)構(gòu) 如果你對(duì)數(shù)據(jù)結(jié)構(gòu)不太熟悉 可以看這篇文章如果你只想看代碼 可以看這篇文章如果你只想star 可以去這里 什么是數(shù)...

    tianhang 評(píng)論0 收藏0
  • JavaScript 數(shù)據(jù)結(jié)構(gòu)與算法之美 - 桶排序、計(jì)數(shù)排序、基數(shù)排序

    摘要:之所以把計(jì)數(shù)排序桶排序基數(shù)排序放在一起比較,是因?yàn)樗鼈兊钠骄鶗r(shí)間復(fù)雜度都為。動(dòng)畫計(jì)數(shù)排序思想找出待排序的數(shù)組中最大和最小的元素。桶排序計(jì)數(shù)排序能派上用場(chǎng)嗎手機(jī)號(hào)碼有位,范圍太大,顯然不適合用這兩種排序算法。 showImg(https://segmentfault.com/img/bVbuF9e?w=900&h=500); 1. 前言 算法為王。 想學(xué)好前端,先練好內(nèi)功,只有內(nèi)功深厚者...

    Awbeci 評(píng)論0 收藏0
  • LeetCode 之 JavaScript 解答第70題 —— 爬樓梯(Climbing Stair

    摘要:小鹿題目假設(shè)你正在爬樓梯。需要階你才能到達(dá)樓頂。你有多少種不同的方法可以爬到樓頂呢注意給定是一個(gè)正整數(shù)。算法思路二種解決思路,第一利用遞歸第二利用動(dòng)態(tài)規(guī)劃。就是因?yàn)橛辛酥貜?fù)元素的計(jì)算,導(dǎo)致了時(shí)間復(fù)雜度成指數(shù)的增長(zhǎng)。 Time:2019/4/12Title:Clibing SrairsDifficulty: EasyAuthor:小鹿 題目:Climbing Stairs You a...

    chemzqm 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<