演算法初級筆記(一)認識時間複雜度

2021-09-20 05:06:42 字數 4039 閱讀 2649

宣告:本筆記所涉及的資料**於牛客網

常數時間的操作:乙個操作如果和資料量沒有關係,每次都是固定時間內完成的操作,叫做常數操作。我的理解是這種操作最終的執行就是執行彙編命令,而彙編命令執行花費的時間都是有限的機器時鐘時間,可以簡單理解為執行乙個相加指令,所以常數操作花費的時間是確定有限的,和數量級沒關係。

時間複雜度為乙個演算法流程中,常數運算元量的指標,常用o(讀作 big o)來表示。具體來說,在常數運算元量的表示式中,只要有高階項,不要低階項,也不要高階項的係數,剩下的部分如果記為f(n),那麼時間複雜度為o(f(n))。

評價乙個演算法流程的好壞,先看時間複雜度的指標,然後再分析不同資料樣本下的實際執行時間,也就是常數項時間。

乙個有序陣列a,另乙個無序陣列b,請列印b中的所有不在a中的數,a陣列長度為n,b陣列長度為m。

這相當於兩個for迴圈,所以常數操作量f(m,n) = m * n ,所以演算法複雜度為o(m * n)

二分查詢常數操作量約為log2n,所以總的演算法複雜度為o(m * logn),log下標可省,一般看做2

排序時間複雜度可為o(m * logm),外排列印時間複雜度為o(m + n),所有總的時間複雜度為o(m * logm) + o(m + n)

所以具體演算法的優劣還要看實際的數量級,演算法二肯定比演算法一要優,演算法二和演算法三需要考慮m,n的取值範圍來判斷

第一次冒:0 ............. n-1

第二次冒:0 ....... n-2

第三次冒:0 ... n-3

直到冒完

所有偽**可以這樣:

public static void bubblesort(int arr) 

for (int e = arr.length - 1; e > 0; e--) }}

}

可知當數量級為n時,常數操作量就是n*n,時間複雜度就為o(n^2),空間複雜度因為只是操作原陣列,沒有聲請什麼額外的空間,所以為常數,額外空間複雜度為o(1)

第一次從0 .................n-1中選擇出最小(大)值放在0

第二次從 1 .................n-1中選擇出最小(大)值放在1

第三次從 2 .................n-1中選擇出最小(大)值放在2

知道選擇完

偽**:

public static void selectionsort(int arr) 

for (int e = 0; e < arr.length-1; e ++)

swap(arr,e,min);

}}

同理:時間複雜度o(n^2),額外空間複雜度o(1)

遞迴的實現實質是方法資料的棧的壓入和彈出,壓入或彈出的資料即為方法的一些屬性資料,如方法指標,引數,結果等

最典型的應用就是歸併排序

套路就是:最外面一層把主問題分為兩個小問題,加乙個merge處理塊

套路公式:

master公式:t(n) = a * t (n / b) + o(n ^ d)

a 為子規模執行次數,b 為主規模分了幾個子規模,d 為merge處理的負責度裡的n的係數

例:歸併排序

public static void mergesort(int arr) 

mergesort(arr, 0, arr.length - 1);

}public static void mergesort(int arr, int l, int r)

int mid = l + ((r - l) >> 1);

mergesort(arr, l, mid);

mergesort(arr, mid + 1, r);

merge(arr, l, mid, r);

}public static void merge(int arr, int l, int m, int r)

while (p1 <= m)

while (p2 <= r)

for (i = 0; i < help.length; i++)

}

最外層將主規模分為了2個子規模f(n/2)執行,所以a = 2,b = 2,merge處理複雜度為o(2n) = o(n) ,所以d = 1,所以t(n) = 2(n/2) + o(n)

所以log(b,a) = d = 1 ,時間複雜度為o(n * logn)

額外空間複雜度為o(n),主要是每次merge都申請了新的陣列空間

小和問題

public static void main(string args)

public static void smallsum(int arr)

system.out.println("原陣列");

util.printarray(arr);

system.out.println("");

int smallsum = deal(arr,0,arr.length-1);

system.out.println("處理後的陣列:");

util.printarray(arr);

system.out.println("小和為:"+smallsum);

}public static int deal(int arr,int left,int right)

int middle = left + ((right-left)>>1);

return deal(arr,left,middle) + deal(arr,middle+1,right)+merge(arr,left,middle,right);

}public static int merge(int arr,int left,int middle,int right)

sum += arr[p1] < arr[p2]? (right-p2+1)*arr[p1]:0;

help[index++] = arr[p1] < arr[p2]? arr[p1++] : arr[p2++];

}while (p1 <= middle)

while (p2 <= right)

for (int i = 0;i < help.length;i++)

return sum;

}

隨機測試結果:

測試結果

在乙個陣列中,左邊的數如果比右邊的數大,則折兩個數構成乙個逆序對,請列印所有逆序對。

public static void main(string args)

public static void nixudui(int arr)

public static void deal(int arr,int left,int right)

int middle = left + ((right-left)>>1);

deal(arr,left,middle);

deal(arr,middle+1,right);

merge(arr,left,middle,right);

}public static void merge(int arr, int left,int middle, int right)

help[i++] = arr[p2++];

}else

}while (p1 <= middle)

while (p2 <= right)

for ( i = 0;i < help.length;i++)

}

執行結果:

逆序對列印

和小和問題是同樣的套路,時間複雜度為o(n * log n),空間複雜度為o(n)

演算法初級筆記(一)認識時間複雜度

宣告 本筆記所涉及的資料 於牛客網常數時間的操作 乙個操作如果和資料量沒有關係,每次都是固定時間內完成的操作,叫做常數操作。我的理解是這種操作最終的執行就是執行彙編命令,而彙編命令執行花費的時間都是有限的機器時鐘時間,可以簡單理解為執行乙個相加指令,所以常數操作花費的時間是確定有限的,和數量級沒關係...

演算法時間複雜度的計算(初級)

在進行演算法分析時,語句總的執行次數t n 是關於問題規模n的函式,進而分析t n 隨n的變化情況並確定t n 的數量級。演算法的時間複雜度,也就是演算法的時間度量,記作 t n o f n 它表示隨問題規模n的增大,演算法執行時間的增長率和f n 的增長率相同,稱作演算法的漸近時間複雜度,簡稱為時...

演算法時間複雜度 一

演算法時間複雜度的定義 在進行演算法分析時,語句總的執行次數t n 是關於問題規模n的函式,進而分析t n 隨n的變化情況並確定t n 的數量級。演算法的時間複雜度記作 t n o f n f n 是問題規模n的某個函式。執行次數 時間 如何分析乙個演算法的時間複雜度 o階推導法 用常數1取代執行時...