您好,登錄后才能下訂單哦!
這篇文章給大家介紹如何解析Java 數(shù)據(jù)結(jié)構(gòu)中時(shí)間復(fù)雜度與空間復(fù)雜度,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
在使用當(dāng)中,算法效率分為兩種,一是時(shí)間效率(時(shí)間復(fù)雜度),二是空間效率(空間復(fù)雜度)。時(shí)間復(fù)雜度是指程序運(yùn)行的速度??臻g復(fù)雜度是指一個(gè)算法所需要的額外的空間。
計(jì)算程序運(yùn)行的時(shí)間不能拿簡單的時(shí)間來計(jì)算,因?yàn)椴煌幚砥魈幚頂?shù)據(jù)的能力是不一樣的。所以只算一個(gè)大概的次數(shù)就行了,儼然就是算法中的基本操作的執(zhí)行次數(shù)。用大O的漸進(jìn)法來表示
例:計(jì)算 func1 的基本操作執(zhí)行了幾次
void func1(int N){ int count = 0; for (int i = 0; i < N ; i++) { for (int j = 0; j < N ; j++) { count++; } } for (int k = 0; k < 2 * N ; k++) { count++; } int M = 10; while ((M--) > 0) { count++; } System.out.println(count); }
func1 的基本執(zhí)行次數(shù)是:F(N) = N^2 + 2*N + 10
1、用常數(shù)1取代運(yùn)行時(shí)間中的所有加法常數(shù)。
2、在修改后的運(yùn)行次數(shù)函數(shù)中,只保留最高階項(xiàng)。
3、如果最高階項(xiàng)存在且不是1,則去除與這個(gè)項(xiàng)目相乘的常數(shù)。得到的結(jié)果就是大O階。
所以使用大 O 的漸進(jìn)法表示之后,func1 的時(shí)間復(fù)雜度就是:O(N^2)
因?yàn)楫?dāng)我們用算法計(jì)算的時(shí)候,會有最好情況和最壞情況和平均情況。我們常說的時(shí)間復(fù)雜度在 O(N) 這里的時(shí)間復(fù)雜度就是最壞情況。
最好情況就是最小的運(yùn)行次數(shù)。
舉例一:
void func2(int N){ int count = 0; for (int k = 0; k < 2 * N ; k++) { count++; } int M = 10; while ((M--) > 0) { count++; } System.out.println(count); }
這里的結(jié)果是 O(N) 因?yàn)楦鶕?jù)時(shí)間復(fù)雜度的計(jì)算方法,去除常數(shù),所以 2*N 就是 N 。M 是 10 也可以忽略掉。
舉例二:
void func3(int N, int M) { int count = 0; for (int k = 0; k < M; k++) { count++; } for (int k = 0; k < N ; k++) { count++; } System.out.println(count); }
這里的時(shí)間復(fù)雜度是 O(M+N) 因?yàn)?M 和 N 的值是未知的,所以是 O(M+N)
舉例三:
void func4(int N) { int count = 0; for (int k = 0; k < 100; k++) { count++; } System.out.println(count); }
這個(gè)的時(shí)間復(fù)雜度是 O(1) 因?yàn)檠h(huán)里面是常數(shù),所以根據(jù)大 O 漸進(jìn)法,結(jié)果就是 O(1)
public static void bubbleSort(int[] arr){ for (int i = 0; i < arr.length; i++) { for (int j = 0; j < arr.length - 1 - i; j++) { if(arr[j] > arr[j+1]){ int tmp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = tmp; } } } }
因?yàn)槊芭菖判虻奶厥庑?,可能一次就排好了,也可能得一直排到最后,所以就有了最好情況和最壞情況。
最好情況:就是比較一次,就是 O(N)
最壞情況:一直排到最后,就是 O(N^2)
int binarySearch(int[] array, int value) { int begin = 0; int end = array.length - 1; while (begin <= end) { int mid = begin + ((end-begin) / 2); if (array[mid] < value) begin = mid + 1; else if (array[mid] > value) end = mid - 1; else return mid; } return -1; }
因?yàn)槎植檎沂且话胍话氲恼遥悦看尾檎抑蠖紩巡檎曳秶鷾p半,比如說在一個(gè) 1 - 8 的有序數(shù)組里面查找 8 也就是查找最壞情況。圖示如下:
如圖,在數(shù)組當(dāng)中完成二分查找需要 log2n - 1 次也就是時(shí)間復(fù)雜度是 log2n (就是 log 以 2 為底 n 的對數(shù))
long factorial(int N) { return N < 2 ? N : factorial(N-1) * N; }
計(jì)算遞歸的時(shí)間復(fù)雜度:遞歸的次數(shù) * 每次遞歸執(zhí)行的次數(shù)。
所以這次遞歸的時(shí)候,基本操作遞歸了 N 次,所以時(shí)間復(fù)雜度就是 O(N)
int fibonacci(int N) { return N < 2 ? N : fibonacci(N-1)+fibonacci(N-2); }
假設(shè) N 是 5 我們來展開求
如圖:每次計(jì)算都會計(jì)算下一層,但是每次都是一邊少,一邊多。所以就可以直接按照每邊一樣來計(jì)算。如下圖:
所以就有公式可以計(jì)算出每次計(jì)算的次數(shù),就是:2 ^ (n - 1) ,所以計(jì)算的結(jié)果就是:2^\0 + 2^1 + 2^2 + 2^3……2^(n-1) = 2^n+1 所以按照大 O 漸進(jìn)法來算,結(jié)果就是:2^n 。
所以斐波那契數(shù)列的時(shí)間復(fù)雜度就是:2^n 。
空間復(fù)雜度衡量的是一個(gè)算法在運(yùn)行過程當(dāng)中占用的額外存儲空間的大小,因?yàn)闆]必要按照字節(jié)來算,而是算變量的個(gè)數(shù)。也是用大 O 漸進(jìn)法表示。
public static void bubbleSort(int[] arr){ for (int i = 0; i < arr.length; i++) { for (int j = 0; j < arr.length - 1 - i; j++) { if(arr[j] > arr[j+1]){ int tmp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = tmp; } } } }
因?yàn)槊芭菖判虻淖兞坎]有變化,使用的是額外空間是常數(shù),所以空間復(fù)雜度是 O(1) 。
int[] fibonacci(int n) { long[] fibArray = new 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; }
因?yàn)檫@里的斐波那契數(shù)列開辟了 n 個(gè)額外空間,所以空間復(fù)雜度為 O(n) 。
int factorial(int N) { return N < 2 ? N : factorial(N-1)*N; }
因?yàn)槭沁f歸,每次遞歸都會開辟棧幀,每個(gè)棧幀占用常數(shù)個(gè)空間,所以空間復(fù)雜度就是 O(N) 。
關(guān)于如何解析Java 數(shù)據(jù)結(jié)構(gòu)中時(shí)間復(fù)雜度與空間復(fù)雜度就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。