日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数据结构算法入门--一文了解什么是复杂度

發(fā)布時間:2023/12/10 编程问答 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构算法入门--一文了解什么是复杂度 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

圖片來自 Pixabay,作者:TeroVesalainen

2019 年第 74 篇文章,總第 98 篇文章

本文大約 3000?字,閱讀大約需要 10?分鐘

最近會開始更新一個數(shù)據(jù)結(jié)構(gòu)算法的學習系列,同時不定期更新 leetcode 的刷題。

這是第一篇文章,在開始介紹各種數(shù)據(jù)結(jié)構(gòu)和算法之前,先了解下什么是復雜度,包括時間復雜度和空間復雜度。

今日推薦閱讀:

精心挑選了這些牛人的公眾號,來看看吧!


什么是復雜度分析

  • 數(shù)據(jù)結(jié)構(gòu)和算法解決是“如何讓計算機更快時間、更省空間的解決問題”。

  • 因此需從執(zhí)行時間和占用空間兩個維度來評估數(shù)據(jù)結(jié)構(gòu)和算法的性能。

  • 分別用時間復雜度和空間復雜度兩個概念來描述性能問題,二者統(tǒng)稱為復雜度。

  • 復雜度描述的是算法執(zhí)行時間(或占用空間)與數(shù)據(jù)規(guī)模的增長關(guān)系

  • 為什么需要復雜度分析

  • 和性能測試相比,復雜度分析有不依賴執(zhí)行環(huán)境、成本低、效率高、易操作、指導性強的特點。

  • 掌握復雜度分析,將能編寫出性能更優(yōu)的代碼,有利于降低系統(tǒng)開發(fā)和維護成本。

  • 如何進行復雜度分析

    對于時間復雜度的分析,通常使用大O復雜度表示法,表示代碼執(zhí)行時間隨數(shù)據(jù)規(guī)模增長的變化趨勢,所以,也叫作漸進時間復雜度(asymptotic time complexity),簡稱時間復雜度

    用公式表示,就是?T(n) = O(f(n))表示,其中?T(n)?表示算法執(zhí)行總時間,f(n)?表示每行代碼執(zhí)行總次數(shù),而?n?表示數(shù)據(jù)的規(guī)模。

    由于時間復雜度描述的是算法執(zhí)行時間與數(shù)據(jù)規(guī)模的增長變化趨勢,所以常量階、低階以及系數(shù)實際上對這種增長趨勢不產(chǎn)決定性影響,所以在做時間復雜度分析時可以忽略這些項。

    具體分析的時候,有下列三個方法:

  • 單段代碼只看循環(huán)次數(shù)最多的部分

  • 多段代碼取復雜度最高的:即有個多個循環(huán),但只看循環(huán)次數(shù)量級最高的那段代碼

  • 乘法法則--嵌套代碼進行乘積:多個循環(huán)嵌套,就是相乘

  • 常見的時間復雜度

    按照數(shù)量級遞增,常見的時間復雜度量級有:

    • 常量階?O(1)

    • 對數(shù)階?O(logn)

    • 線性階?O(n)

    • 線性對數(shù)階?O(nlogn)

    • 平方階?O(n^2),立方階?O(n^3)…k次階?O(n^k)

    • 指數(shù)階?O(2^n)

    • 階乘階?O(n!)

    其中,最后兩種情況是非常糟糕的情況,當然?O(n^2)?也是一個可以繼續(xù)進行優(yōu)化的情況。

    接下來簡單介紹上述復雜度中的幾種比較常見的:

    O(1)

    O(1)?表示的是常量級時間復雜度,也就是只要代碼的執(zhí)行時間不隨 n 的增大而增長,都記作?O(1)?。一般只要算法不包含循環(huán)語句和遞歸語句,時間復雜度都是?O(1)

    像下列代碼,有 3 行,但時間復雜度依然是O(1),而非?O(3)。

    a?=?3 b?=?4 print(a?+?b)
    O(logn)、O(nlogn)

    O(logn)?也是一個常見的時間復雜度,下面是一個?O(logn)?的代碼例子:

    i?=?1 count?=?0 n?=?20 while?i?<=?n:count?+=?1i?*=?2 print('while?循環(huán)運行了?{}?次'.format(count))

    這段代碼其實就是每次循環(huán)都讓變量 i 乘以 2,直到其大于等于 n,這里我設置 n=20,然后運行了后,輸出結(jié)果是循環(huán)運行了 5 次。

    實際上這段代碼的結(jié)束條件,就是求?2^x=n?中的?x?是等于多少,那么循環(huán)次數(shù)也就知道了,而求?x?的數(shù)值,方法就是??,那么時間復雜度就是?

    假如上述代碼進行簡單的修改,將?i *= 2?修改為?i *= 3?,那么同理可以得到時間復雜度就是?

    但在這里,無論是以哪個為對數(shù)的底,我們都把對數(shù)階的時間復雜度記為?O(logn)。

    這里主要原因有兩個:

  • 對數(shù)可以互換,比如?,也就是?,常量

  • 基于前面的理論,系數(shù)可以被忽略,也就是這里的常量 C 可以忽略

  • 基于這兩個原因,對數(shù)階的時間復雜度都忽略了底,統(tǒng)一為?O(logn)?。

    至于?O(nlogn)?,根據(jù)乘法法則,只需要將對數(shù)階復雜度的代碼,運行 n 次,就可以得到這個線性對數(shù)階復雜度了。

    注意,?O(nlogn)?是非常常見的時間復雜度,常用的排序算法如歸并排序、快速排序的時間復雜度都是?O(nlogn)

    O(m+n)、O(m*n)

    前面介紹的情況都是只有一個數(shù)據(jù)規(guī)模?n?,但這里介紹有兩個數(shù)據(jù)規(guī)模的情況--m和?n。

    #?O(m+n) def?cal(n,?m):result?=?0for?i?in?range(n):result?+=?ifor?j?in?range(m):result?+=?j?*?2return?result

    簡單的代碼示例如上述所示,如果事先無法評估?m?和?n?的量級大小,那么這里的時間復雜度就沒法選擇量級最大的,所以其時間復雜度就是?O(m+n)?。

    同理,對于嵌套循環(huán),就是?O(m*n)?的時間復雜度了。

    最好、最壞、平均、均攤時間復雜度

    這四種復雜度的定義如下:

    • 最好情況時間復雜度:代碼在最理想的情況下執(zhí)行的時間復雜度;

    • 最壞情況時間復雜度:代碼在最壞情況下執(zhí)行的時間復雜度;

    • 平均情況時間復雜度:代碼在所有情況下執(zhí)行的次數(shù)的加權(quán)平均值表示

    • 均攤時間復雜度:代碼執(zhí)行的所有復雜度情況中,絕大多數(shù)都是低級別的復雜度,個別情況會發(fā)生最高級別復雜度且發(fā)生具有時序關(guān)系時,可以將個別高級別復雜度均攤到低級別復雜度上。基本上均攤復雜度就等于低級別復雜度,也可以看作是特殊的平均時間復雜度。

    為什么會有這四種復雜度呢?原因是:

    同一段代碼在不同情況下時間復雜度會出現(xiàn)量級差異,為了更全面、更準確描述代碼的時間復雜度,引入這四種復雜度的概念;

    但通常除非代碼是出現(xiàn)量級差別的時間復雜度,才需要區(qū)分這四種復雜度,大多數(shù)情況都不需要區(qū)分它們。

    下面是給出第一個代碼例子:

    #?在數(shù)組?arr?中查找目標數(shù)值?x def?find(arr,?x):for?val?in?arr:if?val?==?x:return?Truereturn?False

    這個例子假設數(shù)組?arr?的長度是?n?,那么它最好的情況,就是第一個數(shù)值就是需要查找的?x?,此時復雜度是?O(1)?,但最壞情況就是最后一個數(shù)值或者不存在需要查找的?x?,那么此時就遍歷一遍數(shù)組,復雜度就是?O(n)?,因此這段代碼最好和最壞情況是會出現(xiàn)量級差別的,O(1)?和?O(n)?分別是最好情況復雜度和最壞情況復雜度。

    而這段代碼的平均情況時間復雜度是?O(n)?,具體分析就是首先考慮所有可能的情況以及對應出現(xiàn)的概率,可能發(fā)生的情況先分為兩種,存在和不存在需要查找的數(shù)值?x,也就是分別是 1/2 的概率,然后對于存在的情況下,又有?n?種情況,即出現(xiàn)在數(shù)組任意位置的概率都是均等的,那么它們的概率乘以存在的概率就是?1/2n?,接著再考慮每種情況需要搜索的元素個數(shù),其實就是代碼執(zhí)行的次數(shù),這個分別就是從 1 到 n,并且對于不存在的情況,也是 n ,需要遍歷一遍數(shù)組才發(fā)現(xiàn)不存在,所以平均時間復雜度的計算過程如下:加權(quán)平均值,也叫期望值,所以平均時間復雜度的全稱應該叫加權(quán)平均時間復雜度或者期望時間復雜度

    這里用大 O 表示法表示,并且去掉常量和系數(shù)后,就是 O(n)。

    最后介紹下均攤時間復雜度,需要滿足以下兩個條件才使用:

    1)代碼在絕大多數(shù)情況下是低級別復雜度,只有極少數(shù)情況是高級別復雜度

    2)低級別和高級別復雜度出現(xiàn)具有時序規(guī)律均攤結(jié)果一般都等于低級別復雜度

    空間復雜度分析

    和時間復雜度的定義類似,空間復雜度全稱就是漸進空間復雜度(asymptotic space complexity),表示算法的存儲空間與數(shù)據(jù)規(guī)模之間的增長關(guān)系

    簡單介紹下一個程序所需要的空間主要由以下幾個部分構(gòu)成:

    • 指令空間:是值用來存儲經(jīng)過編譯之后的程序指令所需要的空間。

    • 數(shù)據(jù)空間:是指用來存儲所有常量和變量值所需的空間。其主要由兩個部分構(gòu)成:

      • 存儲常量和簡單變量所需要的空間

      • 存儲復合變量所需要的空間。這一類空間包括數(shù)據(jù)結(jié)構(gòu)所需要的動態(tài)分配的空間

    • 環(huán)境棧空間:用來保存函數(shù)調(diào)用返回時恢復運行所需要的信息。例如,如果函數(shù) fun1 調(diào)用了函數(shù) fun2,那么至少必須保存 fun2 結(jié)束時 fun1 將要繼續(xù)執(zhí)行的指令的地址。


    本系列主要參考極客時間上的數(shù)據(jù)結(jié)構(gòu)與算法之美課程,目前這門課正在做活動,拼團只需 65 元,課程的設計非常合理,而且介紹得很詳細,有對應的代碼輔助理解,還有一個開源的 GitHub,目前已經(jīng)有1w+的star了:

    https://github.com/wangzheng0822/algo

    歡迎關(guān)注我的微信公眾號--算法猿的成長,或者掃描下方的二維碼,大家一起交流,學習和進步!

    如果覺得不錯,在看、轉(zhuǎn)發(fā)就是對小編的一個支持!

    總結(jié)

    以上是生活随笔為你收集整理的数据结构算法入门--一文了解什么是复杂度的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。