O(n):用於演算法複雜度的大O符號表示法
21CTO導讀:大O符號,英語稱為Big O Notation,用於描述演算法複雜度的漸進表示,它描述了演算法如何通過其增長的上界來執行擴充套件。

大O演算法是我在大學教過的東西之一,但是我其實從來沒有掌握過這些概念,讀書時我自己覺得能夠足夠回答這個符號的基本問題。
從那時候起沒有什麼任何改變。從我參加工作以來,也沒有用過,也很少聽到其他的同事提起過它。
在本文中,我想花一些時間來寫一篇文章來總結大寫O演算法的基礎知識 ,包括一些程式碼例項來輔助說明。
Big O Natiation是什麼?來簡單解釋一下:
1、它是演算法複雜度的相對錶示方式
2、它描述了演算法如何執行與擴充套件
3、它描述了函式增長能力的上限,可以理解為最不好的情形
快速檢視演算法: O(n2) .
其中:n是函式作為輸入接收的元素個數。上面的公式表示有n個輸入,其複雜度為 (n2), 這是一種速度較慢的排序演算法。
表1:共同複雜度的比較
從上表中可以看到,隨著函式的演算法複雜度不斷增加,完成函式所需要的時間越明顯增加。在程式設計過程中,我們希望讓這種遞增儘可能地低,如果某個函式在輸入增加時不能很好的擴充套件,那麼極有可能導致效能糟糕的問題。
程式員還是適合用程式碼說話,下面的程式碼用Java編寫,將有助於你清晰瞭解演算法複雜度是如何影響效能的。
O(1)
public boolean isFirstNumberEqualToOne(List<Integer> numbers){
return number.get(0) == 1;
}
O(1)為提供一個函式,始終通過外部獲得固定的輸入引數。
O(n)
public boolean containsNumber(List<Integer> numbers, int comparisonNumber) {
for(Integer number : numbers) {
if(number == comparisonNumber) {
return true;
}
}
return false;
}
O(n)表示函式的複雜性,也稱線性時間,該函式線性增加並與輸入數量成正比。 這是Big O Notation如何描述最糟糕情況的一個很好例子,因為函式可以在讀取第一個元素後返回true,或者在讀取所有n個元素後返回false。這樣的演算法包括簡單查詢。
O(n2)
public static boolean containsDuplicates(List<String> input) {
for (int outer = 0; outer < input.size(); outer++) {
for (int inner = 0; inner < input.size(); inner++) {
if (outer != inner && input.get(outer).equals(input.get(inner))) {
return true;
}
}
}
return false;
}
O(n2)表示其複雜度與輸入大小的平方成正比的函式。 通過輸入新增更多巢狀迭代將增加複雜度,其可以表示為具有3次總迭代的 O(n3) 和具有4次總迭代的 O(n4) 。
O(2 n )
public int fibonacci(int number) {
if (number <= 1) {
return number;
} else {
return fibonacci(number - 1) + fibonacci(number - 2);
}
}
O(2[size=25]n )表示一個函式,其效能對於輸入中的每個元素都加倍。 這個例子是Fibonacci陣列的遞迴計算。 該函式屬於 O(2 n ) ,因為函式遞迴式為每個輸入數字呼叫兩次,直到該數字小於或等於1。[/size]
O(log n)
public boolean containsNumber(List<Integer> numbers, int comparisonNumber) {
int low = 0;
int high = numbers.size() - 1;
while (low <= high) {
int middle = low + (high - low) / 2;
if (comparisonNumber < numbers.get(middle)) {
high = middle - 1;
} else if (comparisonNumber > numbers.get(middle)) {
low = middle + 1;
} else {
return true;
}
}
return false;
}
O(log n) ,也稱對數時間,表示隨著輸入大小的增加其複雜度以對數方式增加的函式。 這使得 O(log n) 函式可以很好地擴充套件,因此處理較大的輸入不太可能導致效能問題。 上面的示例使用二進位制搜尋來檢查輸入列表是否包含特定數字。
簡單來說,它在每次迭代時將列表拆分為兩個,直到找到數字或讀取最後一個元素。 該方法具有與 O(n) [size=19] 示例相同的功能 - 儘管實現完全不同並且更難以理解。 但是,通過更大的輸入可以獲得更好的效能(如上表中所示)。[/size]
小結
當前,我們獲得的啟示如下:
1 演算法的速度指的並非時間,非運算元的增速
2 談論演算法的速度時,我們說的是隨著輸入的增加,其執行時間將以什麼樣的速度增加
3 演算法的執行時間用大O表示法表示
4 O(log n)比O(n)快,當需要搜尋的元素越多時,前者比後者快得越多。
關於Big O Notation還能寫出很多內容。希望大家對Big O Notation的含義以及如何將其轉換為自己編寫的程式碼有一個基本概念。
作者:老夏