演算法
即存在輸入輸出,由有限步驟結束的程式.
因此,顯而易見,演算法並不是指一個單一的標準答案,而是一切能夠完成要求的程式都可以稱之為演算法.但是演算法之間根據效能的不同存在差異,評判這個差異的指標就是本篇分享的重點.
評判演算法優劣的指標
1.時間複雜度
時間複雜度用O()表示,它的實質是演算法的計算次數
這裡先列舉幾個小例子
第一個例子
int n,ans=0;
cin>>n;
for(int i=0;i<n;i++){
ans++;
}
ans++;
ans++;
ans++;
cout<<ans;
這段程式比較好理解,在這裡,for迴圈中進行了n次運算,而之後對ans又進行了3次運算,在這裡我們的有效計算次數為n+3.
但是這裡需要注意時間複雜度並不是n+3,因為我們在實際操作時,n是會取到無窮大的,在這裡n就是無窮,對於無窮來說,3就可以忽略不計,因此這段程式的時間複雜度為O(n).
再看一下第二個例子
int n,ans=0;
cin>>n;
for(int i=0;i<n;i+=2){
ans++;
}
cout<<ans;
這次不過多解釋,有效計算次數為n/2,但因為n是趨於無窮的,所以時間複雜度仍然為O(n).
第三個例子
int n,ans=0;
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
ans++;
}
}
for(int i=1;i<=n;i++){
ans++;
}
cout<<ans;
這次的程式碼有兩個迴圈,第二個是n,第一個則是作為一個巢狀迴圈,比較容易得出經過了n*n次迴圈
這次的有效計算次數為n2+n,由於n趨向無窮,對n2來說,n可以忽略不計,所以這次的時間複雜度為O(n2).
最後一個例子
int arr[101];
int n;
cin>>n;
for(int i=0;i<n;i++) cin>>arr[i];
for(int i=n-1;i>0;i++){
for(int j=0;j<i;j++){
if(arr[j]>arr[j+1]){
swap(arr[j],arr[j+1]);
}
}
}
這是一個氣泡排序演算法,這次的有效計算次數為1+2+3+...+n-1,由等差數列的求和公式知道為(n2+n)/2.經過前面的例子,想必都知道了時間複雜度就是不帶係數最高次項,這裡就是O(n2)
經過上面的例子大家應該對演算法的時間複雜度有了比較清晰的認識,這裡我再補充幾點
1.有限計算次數即沒有n加入的程式,規定時間複雜度為O(1).
2.常見的時間複雜度有:O(1),O(logn),O(n),O(n2),O(n3).
2.空間複雜度
事實上在實際情況下,空間複雜度沒有時間複雜度受重視,在實際學習中,大多數情況下是超過了執行時間,而不是超過規定記憶體.但它同樣需要我們瞭解.
時空複雜度也用O()表示,它的實質是額外產生的空間.
int arr[101];
int n;
cin>>n;
for(int i=0;i<n;i++) cin>>arr[i];
int *arr=new int[n];
for(int i=n-1;i>0;i++){
for(int j=0;j<i;j++){
if(arr[j]>arr[j+1]){
swap(arr[j],arr[j+1]);
}
}
}
delete[]arr;
這裡需要關注的是空間複雜度是額外產生的空間,因此初始的n個不計入空間複雜度,而之後的new出來的記憶體是空間複雜度,即為n,它的計算方法和時間複雜度一樣,取不帶係數的最高次項.
補充幾點:
1.時間和空間往往是相對的.
2.常見的空間複雜度:O(1),O(n),O(logn*n)
3.穩定性
這裡簡單提一下,不過多贅述,後續會專門開一個新坑講解一下.