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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

时间复杂度和空间复杂度 详谈

發布時間:2024/3/24 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 时间复杂度和空间复杂度 详谈 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

1.算法效率問題引出

2.算法的復雜度:

3.時間復雜度

3.1時間復雜度的概念:

3.2注意事項

3.3時間復雜度代碼示例

?3.4大O漸進表示法:

3.5?函數增幅表

3.6?時間復雜度代碼示例

3.6.1?循環

3.6.2?二分查找

3.6.3?遞歸函數

3.6.4斐波那契數列

4.空間復雜度

4.2.時間與空間的關系

4.3代碼示例

4.3.1基本函數空間復雜度

4.3.2?斐波那契數列空間復雜度

4.3.3?返回前n項的斐波那契


1.算法效率問題引出

經典問題:斐波那契數列——兔子問題的解決?

#include<stdio.h>long long Fib(int n) {if (n < 3){return 1;}return Fib(n - 1) + Fib(n - 2); }int main() {int n = 0;scanf("%d", &n);int ret = Fib(n);printf("%d", ret);return 0; }

?代碼實現利用遞歸看似簡單,但是這種代碼運行起來效果好嗎?

2.算法的復雜度:

1.算法在編寫成可執行程序后,運行時需要耗費時間資源空間資源 。因此衡量一個算法的好壞,一般是從時間和空間兩個維度來衡量的,即時間復雜度和空間復雜度。
2.時間復雜度主要衡量一個算法的運行快慢,而空間復雜度主要衡量一個算法運行所需要的額外空間

3.時間復雜度

3.1時間復雜度的概念:

在計算機科學中,算法的時間復雜度是一個函數,它定量描述了該算法的運行時間。一個算法執行所耗費的時間,從理論上說,是不能算出來的,只有你把你的程序放在機器上跑起來,才能知道。這很麻煩,所以才有了時間復雜度這個分析方式。一個算法所花費的時間與其中語句的執行次數成正比例,算法中的基本操作的執行次數,為算法的時間復雜度。

我認為,時間復雜度就是當我們為解決問題編寫的代碼中,一個程序從開始到結束,需要對數據進行處理的代碼語句重復所執行的次數,(算法中基本語句操作的重復執行次數),就是時間復雜度。?

3.2注意事項

1.定義中說算法的時間復雜度是一個函數,而這個函數,并非我們在C語言中所將的功能函數,而是我們在數學中所認識的函數,是Y與X的關系式,是為了描述某種數學現象而分析總結出的結論。

2.實際中我們計算時間復雜度時,我們其實并不一定要計算精確的執行次數,而只需要大概執行次數,那么這里我們使用大O的漸進表示法。

3.一個算法會有最好的情況,平均情況和?最差的情況,我們只看最差情況。

3.3時間復雜度代碼示例

#include<stdio.h>void Fuc(int N) {int count = 0;for (int i = 0; i < N; i++){for (int j = 0; j < N; j++){count++; // 這里雙for循環 所以這里執行N^2}}for (int k = 0; k < N; k++){count++; // 這里for循環 所以這里執行N }int ret = 5;while (ret){count++; // 這里執行5次ret--;}return 0; }

?

上面代碼我們可以看出,這個代碼的時間復雜度應該是函數T(N)= N^2 +N + 5;可結果真的是這樣嗎?可答案卻并非如此,真正的答案是O(N^2),這是為什么呢?

因為我們在實際計算時間復雜度時,我們其實并不一定要精確的計算我們的執行次數,只需要一個大概的執行次數,而這里我們就需要用到“大O的漸進表示法”
?

?3.4大O漸進表示法:


大O符號(Big O notation):是用于描述函數漸進行為的數學符號。 推導大O階方法:
1.用常數1取代運行時間中的所有加法常數。? ? ? ? ? ? ? F(N) =? 常數? ?===> ? O(1);
2.在修改后的運行次數函數中,只保留最高階項。?? ? F(N)= ?2N^2+3N+10 ?===> ? N^2 ?;
3.如果最高階項存在且不是1,則去除與這個項目相乘的常數。得到的結果就是大O階。
4.如果執行了M 次 和N次 ,則一共M+N;? ? ? ? ? ? ? ? ? F(M, N) = M + N == == > O(M + N);?

3.5?函數增幅表

3.6?時間復雜度代碼示例

3.6.1?循環

void Func1(int N, int M) {int count = 0;for (int k = 0; k < M; ++k) // 執行M次{++count;}for (int k = 0; k < N; ++k) // 執行N次{++count;}printf("%d\n", count); }

? 總共執行次數:M+N;

3.6.2?二分查找

// 二分法第一種 寫法 【begin,end】 int BinarySearch1(int* a, int n, int x)//折中查找 {assert(a);//傳遞數組int begin = 0;//首標int end = n - 1;//尾標 // 采用左閉右閉【begin,end】while (begin <= end){int mid = begin + ((end - begin) >> 1);if (a[mid] < x)begin = mid + 1;else if (a[mid] > x)end = mid-1;elsereturn mid;}return -1; } // 二分法第一種 寫法 【begin,end) int BinarySearch2(int* a, int n, int x)//折中查找 {assert(a);//傳遞數組int begin = 0;//首標int end = n ;//尾標 // 采用左閉右開【begin,end)while (begin < end){int mid = begin + ((end - begin) >> 1);if (a[mid] < x)begin = mid + 1;else if (a[mid] > x)end = mid;elsereturn mid;}return -1; }

?注意:二分法代碼書寫,一定要注意區間是左閉右開,還是左閉右閉,因為這個條件會決定后面的代碼書寫。

?畫圖分析:

上面的圖片解析的含義是說:在一個有序數組中,首先確定當前可尋找范圍內的中間值,然后與目標數進行對比,然后判斷是小還是大,然后對當前尋找范圍砍半,重復上面的步驟,直到尋找到目標數,而這重復的步驟去尋找目標數,就是執行次數,即時間復雜度;

注意:時間復雜度為 O(logN),(logN在算法分析中表示是底數為2,對數為N)有些地方會寫成lgN?

3.6.3?遞歸函數的時間復雜度

long long Func2(int N)//遞歸函數 {if (N == 1)return 1;return Func2(N - 1)*N; }

?此函數時間復雜度為:O(N)

3.6.4斐波那契數列的時間復雜度

long long Fib(int N)//斐波那契數列 {if (N < 3)return 1;return Fib(N - 1) + Fib(N - 2); }

?面對斐波那契數列的時間復雜度的分析,我的理解是通過畫圖尋找的結果
下面是我的分析:

當我們第一次進入Fib函數時,會第一次支出代碼塊中的內容,此時會產生Fib(N-1)和Fib(N-2),然后通過遞歸,進入第二次Fib函數,此時在面對第一次產生的兩個Fib函數,各自再一次進行代碼塊的內容,產生對應的Fib函數,直到Fib函數中的"N"< 3,結束遞歸,開始逐一返回,結束程序,此時,通過畫圖來對時間復雜度進行計算
??其中,在上面的圖解中,有一部分內容我進行了省略,這省略的部分是指,在每一次的遞歸中,越是在后面的遞歸(指圖中同一行,越靠右的Fib函數)它們會更早的使Fib函數中的形參"N" < 3,使得遞歸結束,但對這些提早結束遞歸的Fib函數,它們的執行次數其實是有限的,為一個常數,需要將它們減去,但又因為我們上述的口訣,其對O階影響不大,任然會去除,最終的結果任然是O(2^N)。

4.空間復雜度

空間復雜度也是一個數學表達式,是對一個算法在運行過程中臨時占用存儲空間大小的量度?
空間復雜度不是程序占用了多少bytes的空間,因為這個也沒太大意義,所以空間復雜度算的是變量的個數。空間復雜度計算規則基本跟時間復雜度類似,也使用大O漸進表示法。

注意:函數運行時所需要的棧空間(存儲參數、局部變量、一些寄存器信息等)在編譯期間已經確定好了,因此空間復雜度主要通過函數在運行時候顯式申請的額外空間來確定。

4.2.時間與空間的關系(重點)

核心:時間是累計的,空間是可重復利用的

關于對這句話的理解,我會在下面空間復雜度的分析中,與上面時間復雜度的例題進行同步分析,便于理解

4.3代碼示例

4.3.1基本函數空間復雜度

void Func2(int N) {for (int i = 0; i < N; i++) //在Func2函數棧幀中創建了變量i;{printf("hello");}for (int j = 0; j < N; j++) //在Func2函數棧幀中創建了變量j;{pirntf("hi");}while (N--) // 一個創建了兩個變量,是常數。{printf("你好");}}

空間復雜度:O(1)

4.3.2?斐波那契數列空間復雜度

long long Fib(int N)//斐波那契數列 {if (N < 3)return 1;return Fib(N - 1) + Fib(N - 2); }

這一題是上述講解時間復雜度時的斐波那契數列問題,我們用這個題目,來講解時間復雜度和空間復雜度的關系:時間是可以累積的,空間是可重復利用的

首先,我們對計算機中內存的大概情況進行一個回顧,我用一個圖片進行描述:

?

?①而我們在計算空間復雜度時,我有講到:對空間復雜度的計算是在棧區中,對一個棧幀中變量數目的記錄統計,而如果我們創造了多個棧幀,那么就需要記錄每一個棧幀中創建的變量數目,最后加合統計,得出該函數的空間復雜度。

②而上面我們提到“時間是可以累積的,空間是可重復利用的”,這句話是說,當我們計算時間復雜度時,每在一個循環條件或者遞歸條件中,執行一次操作,就記錄一次;

③而在求解空間復雜度時,如遞歸問題中,當某一個棧幀執行結束時,這個棧幀的空間就會被釋放,這個地方的空間就暫時無人使用,但其他遞歸函數再一次運行時,這一處的空間,可能會再一次用來執行剛剛被釋放的遞歸函數內的代碼塊,所以空間是可以充分利用的。


在對待這一道題目,我們從時間復雜度的角度考慮,得出的是下面這張圖片

?

而當我們從空間復雜度的角度考慮這道題目時,我們可以按照我下面的這張圖的思路分析?

?

?理解:執行Fib(N)函數時,首先執行Fib(N-1),再執行Fib(N-2).在后面的遞歸循環里面都會先執行Fib(N-1),就是先執行左邊的直到到頭。這樣的話就會從Fib(N)?一直執行到Fib(2),然后釋放Fib(2)的空間,返回到Fib(3),此時會重新利用剛才釋放Fib(2)的空間,來執行Fib(1),而不會再開辟新的空間。再返回Fib(3),然后繼續往后調。而等到Fib(N-1)結束后,在開始Fib(N-2),因為Fib(N-2),沒有Fib(N-1)深入,所以使用空間資源也沒有Fib(N-1)多,所以按照最多的算。 Fib(N)到Fib(2)一共 N-1個。所以空間復雜度O(N-1)-->O(N);?每一次調用函數的空間大小是一定的,調用了N-1次。

空間復雜度就是:?新開辟的空間。

4.3.3?返回前n項的斐波那契數列的時間復雜度和空間復雜度

// 時間復雜度O(n)// 空間復雜度O(n) long long* Fibonacci(size_t n){ //定義一個函數,系統給他開辟一個棧空間。 if (n == 0)return NULL; long long* fibArray = (long long*)malloc((n + 1)* sizeof(long long));// 運行期間 還從 堆上申請了一個空間 (n+1). 申請的是堆上的。fibArray[0] = 0; fibArray[1] = 1;for (int i = 2; i <= n; ++i){fibArray[i] = fibArray[i - 1] + fibArray[i - 2];}return fibArray;

關于時間復雜度和空間復雜度,在這里就結束了,如果學到了東西。還希望老鐵能點贊,關注。

總結

以上是生活随笔為你收集整理的时间复杂度和空间复杂度 详谈的全部內容,希望文章能夠幫你解決所遇到的問題。

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