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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

看动画轻松理解时间复杂度(一)

發布時間:2023/12/10 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 看动画轻松理解时间复杂度(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

算法(Algorithm)是指用來操作數據、解決程序問題的一組方法。對于同一個問題,使用不同的算法,也許最終得到的結果是一樣的,比如排序就有前面的十大經典排序和幾種奇葩排序,雖然結果相同,但在過程中消耗的資源和時間卻會有很大的區別,比如快速排序與猴子排序:)。

那么我們應該如何去衡量不同算法之間的優劣呢?

主要還是從算法所占用的「時間」和「空間」兩個維度去考量。

  • 時間維度:是指執行當前算法所消耗的時間,我們通常用「時間復雜度」來描述。

  • 空間維度:是指執行當前算法需要占用多少內存空間,我們通常用「空間復雜度」來描述。

本小節將從「時間」的維度進行分析。

什么是大O

當看「時間」二字,我們肯定可以想到將該算法程序運行一篇,通過運行的時間很容易就知道復雜度了。

這種方式可以嗎?當然可以,不過它也有很多弊端。

比如程序員小吳的老式電腦處理10w數據使用冒泡排序要幾秒,但讀者的iMac Pro 可能只需要0.1s,這樣的結果誤差就很大了。更何況,有的算法運行時間要很久,根本沒辦法沒時間去完整的運行,還是比如猴子排序:)。

那有什么方法可以嚴謹的進行算法的時間復雜度分析呢?

有的!

「 遠古 」的程序員大佬們提出了通用的方法:「 大O符號表示法 」,即 T(n) = O(f(n))

其中 n 表示數據規模 ,O(f(n))表示運行算法所需要執行的指令數,和f(n)成正比。

上面公式中用到的 Landau符號是由德國數論學家保羅·巴赫曼(Paul Bachmann)在其1892年的著作《解析數論》首先引入,由另一位德國數論學家艾德蒙·朗道(Edmund Landau)推廣。Landau符號的作用在于用簡單的函數來描述復雜函數行為,給出一個上或下(確)界。在計算算法復雜度時一般只用到大O符號,Landau符號體系中的小o符號、Θ符號等等比較不常用。這里的O,最初是用大寫希臘字母,但現在都用大寫英語字母O;小o符號也是用小寫英語字母o,Θ符號則維持大寫希臘字母Θ。

注:本文用到的算法中的界限指的是最低的上界。

常見的時間復雜度量級

我們先從常見的時間復雜度量級進行大O的理解:

  • 常數階O(1)

  • 線性階O(n)

  • 平方階O(n2)

  • 對數階O(logn)

  • 線性對數階O(nlogn)

O(1)

無論代碼執行了多少行,其他區域不會影響到操作,這個代碼的時間復雜度都是O(1)

1void?swapTwoInts(int?&a,?int?&b){
2??int?temp?=?a;
3??a?=?b;
4??b?=?temp;
5}

O(n)

在下面這段代碼,for循環里面的代碼會執行 n 遍,因此它消耗的時間是隨著 n 的變化而變化的,因此可以用O(n)來表示它的時間復雜度。

1int?sum?(?int?n?){
2???int?ret?=?0;
3???for?(?int?i?=?0?;?i?<=?n?;?i?++){
4??????ret?+=?i;
5???}
6???return?ret;
7}

特別一提的是 c * O(n) 中的 c 可能小于 1 ,比如下面這段代碼:

1void?reverse?(?string?&s?)?{
2????int?n?=?s.size();
3????for?(int?i?=?0?;?i?<?n/2?;?i++){
4??????swap?(?s[i]?,?s[n-1-i]);
5????}
6}

O(n2)


當存在雙重循環的時候,即把 O(n) 的代碼再嵌套循環一遍,它的時間復雜度就是 O(n2) 了。

?

1void?selectionSort(int?arr[],int?n){
2???for(int?i?=?0;?i?<?n?;?i++){
3?????int?minIndex?=?i;
4?????for?(int?j?=?i?+?1;?j?<?n?;?j++?)
5???????if?(arr[j]?<?arr[minIndex])
6???????????minIndex?=?j;
7
8?????swap?(?arr[i],?arr[minIndex]);
9???}
10}

這里簡單的推導一下

  • 當 i = 0 時,第二重循環需要運行 (n - 1) 次
  • 當 i = 1 時,第二重循環需要運行 (n - 2) 次
  • 。。。。。。

不難得到公式:

1(n?-?1)?+?(n?-?2)?+?(n?-?3)?+?...?+?0
2=?(0?+?n?-?1)?*?n?/?2
3=?O?(n?^2)

當然并不是所有的雙重循環都是 O(n2),比如下面這段輸出 30n 次 Hello,五分鐘學算法:)的代碼。

1void?printInformation?(int?n?){
2???for?(int?i?=?1?;?i?<=?n?;?i++)
3????????for?(int?j?=?1?;?j?<=?30?;?j?++)
4???????????cout<<?"Hello,五分鐘學算法:)"<<?endl;
5}

O(logn)

1int?binarySearch(?int?arr[],?int?n?,?int?target){
2??int?l?=?0,?r?=?n?-?1;
3??while?(?l?<=?r)?{
4????int?mid?=?l?+?(r?-?l)?/?2;
5????if?(arr[mid]?==?target)?return?mid;
6????if?(arr[mid]?>?target?)?r?=?mid?-?1;
7????else?l?=?mid?+?1;
8??}
9??return?-1;
10}

在二分查找法的代碼中,通過while循環,成 2 倍數的縮減搜索范圍,也就是說需要經過 log2^n 次即可跳出循環。

同樣的還有下面兩段代碼也是 O(logn) 級別的時間復雜度。

1??//?整形轉成字符串
2??string?intToString?(?int?num?){
3???string?s?=?"";
4???//?n?經過幾次“除以10”的操作后,等于0
5???while?(num?){
6????s?+=?'0'?+?num%10;
7????num?/=?10;
8???}
9???reverse(s)
10???return?s;
11??}
1void?hello?(int?n?)?{
2???//?n?除以幾次?2?到?1
3???for?(?int?sz?=?1;?sz?<?n?;?sz?+=?sz)?
4?????for?(int?i?=?1;?i?<?n;?i++)
5????????cout<<?"Hello,五分鐘學算法:)"<<?endl;
6}

O(nlogn)

將時間復雜度為O(logn)的代碼循環N遍的話,那么它的時間復雜度就是 n * O(logn),也就是了O(nlogn)。

1void?hello?(){
2??for(?m?=?1?;?m?<?n?;?m++){
3????i?=?1;
4????while(?i?<?n?){
5????????i?=?i?*?2;
6????}
7???}
8}

更多復雜度分析內容可以在公眾號 五分鐘學算法 獲取

轉載于:https://www.cnblogs.com/fivestudy/p/10113337.html

總結

以上是生活随笔為你收集整理的看动画轻松理解时间复杂度(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。