手撕面試題演算法 排序 (4) 歸併排序

2021-10-10 04:27:06 字數 2100 閱讀 1223

歸併排序是乙個相當快速的演算法,其時間複雜度穩定在o(n*logn),在面試中被問到的頻率也挺高的,今天就來介紹一下這個排序演算法

手撕面試題演算法<排序>(1)—— 氣泡排序及其優化實現

手撕面試題演算法<排序>(2)—— 選擇排序

手撕面試題演算法<排序>(3)—— 插入排序及其優化實現

手撕面試題演算法<排序>(3.5)—— 希爾排序

手撕面試題演算法<排序>(4)—— 歸併排序

手撕面試題演算法<排序>(5)—— 快速排序以及快排為什麼快

手撕面試題演算法<排序>(6)—— 堆 & 堆排序

手撕面試題演算法<排序>(7)—— 箱排序 & 基數排序

看完有收穫別忘了點個star哦~ 測試

在歸併排序中體現的是分治的思想,其將乙個陣列一分為二,二分為四,直到不能再分——將難以處理的大問題拆分成容易處理的小問題,最後再將排序完畢的陣列合併在一起,完成陣列的排序

將乙個陣列對半拆分處理的時間複雜度是o(logn)

例,對乙個長度為n的陣列進行遞迴拆分:

而每次對子區間的排序的次數為:

所以歸併排序總共需要走logn次o(n)的操作,的時間複雜度為 o(n*logn)

我們使用遞迴來將陣列進行拆分

通過傳入的陣列,以及區間[l, r],來對半劃分陣列,並將劃分後的l, r記錄下來進行下一次遞迴,直到l >= r

private

static

void

sort

(int

arr,

int l,

int r)

}

陣列的歸併就是將兩條陣列重排序後合併成一條陣列的過程

private

static

void

merge

(int

arr,

int l,

int mid,

int r)

while

(i <= mid) tmparr[idx++

]= arr[i++];

while

(j <= r) tmparr[idx++

]= arr[j++];

// 將tmparr陣列中排序完畢的值放回原陣列中

for(

int val : tmparr)

}

這個過程跟手撕面試題演算法<鍊錶> (1)——鍊錶合併系列非常類似,可以參考一下

上面的sort遞迴方法需要傳入l和r,對使用者來說不太友好,我們可以過載乙個只需要傳入陣列的sort入口方法:

public

static

void

sort

(int

arr)

排序測試:

百萬級陣列測試:

int n =

1_000_000;

int[

] arr = tester.

randomarr

(n);

system.out.

println

("對有"

+ n +

"個元素的隨機數組進行排序:");

long start = system.

currenttimemillis()

;sort

(arr)

;long end = system.

currenttimemillis()

; system.out.

println

("歸併排序結束,耗時"

排序演算法(4) 歸併排序

簡介 歸併排序是建立在歸併操作上的一種有效的排序演算法,該演算法是採用分治法 divide and conquer 的乙個非常典型的應用。將已有序的子串行合併,得到完全有序的序列 即先使每個子串行有序,再使子串行段間有序。若將兩個有序表合併成乙個有序表,稱為二路歸併。一 主要步驟 將待排序陣列 0....

手撕演算法 排序

時間複雜度o n 2 o n 2 o n2 空間複雜度 o 1 穩定 從第乙個元素開始,認為左邊的序列是有序的,從有序部分的最後乙個向前比較,如果當前元素小於有序部分就交換,否則比較下乙個元素。function insertmerge arr else return arr let arr 1 5,...

4 歸併排序演算法

1 歸併排序 merge sort 基本思想 歸併排序法是將兩個或兩個以上的有序表合併成乙個新的有序表 即將待排序的序列分成若干個子串行,每個子串行是有序的,然後再把有序子串行合併為整體子串行 利用歸併的思想實現二路歸併排序的實現步驟 首先將整個資料表看成是n個有序子表,每個子表長度為1 當然有序啦...