歸併排序的思想是把陣列不斷分割成兩半,然後不斷合併,具體就是先遞迴將陣列分成兩半分別排序,然後將結果歸併起來。分割的過程屬於遞迴行為,而合併過程用到了外排序的方法。
外排序:用兩個指標指向兩個已排好序的陣列,申請乙個大小為n(n為兩個陣列大小的和,n最大為原始陣列的大小)的陣列,把指標指向較小的數放進去(當兩指標指向的數相等時,左邊?的指標移動指標右移乙個單位),當某個指標越界時,另一邊的數全部拷貝進陣列。該過程申請的陣列占用了n,所以空間複雜度為o(n)。
時間複雜度:o(n*logn)
空間複雜度:o(n)
public
class
mergesort
mergesort
(arr,
0, arr.length -1)
;}public
static
void
mergesort
(int
arr,
int left,
int right)
int mid = left +
(right - left)/2
;mergesort
(arr, left, mid)
;mergesort
(arr, mid +
1, right)
;merge
(arr, left, mid, right);}
public
static
void
merge
(int
arr,
int left,
int mid,
int right)
while
(p1 <= mid)
while
(p2 <= right)
for(i =
0; i < help.length; i++)}
public
static
void
printarray
(int
arr)
}public
static
void
main
(string[
] args)
;printarray
(arr)
;mergesort
(arr)
; system.out.
println()
;printarray
(arr);}
}
題目:小和問題和逆序對問題
小和問題 在乙個陣列中,每乙個數左邊比當前數小的數累加起來,叫做這個陣列的小和。求乙個陣列的小和。
例子:[1,3,4,2,5] 1左邊比1小的數,沒有; 3左邊比3小的數,1; 4左 邊比4小的數,1、3; 2左邊比2小的數,1; 5左邊比5小的數,1、3、4、 2; 所以小和為1+1+3+1+1+3+4+2=16
思路:把小和問題轉換為求每個數右邊比當前數大的數的累加,然後用歸併排序的外排序進行計算。
改進點:在外排序部分進行小和的計算,與歸併排序的不同點是左部分《右部分時才移動左指標,相等時移動右指標。當左部分《右部分時,計算出(r-p2+1)*arr[p1],r右邊界,p1左指標,p2右指標。
code如下:
public
static
intsmallsum
(int
arr)
return
mergesort
(arr,
0, arr.length -1)
;}public
static
intmergesort
(int
arr,
int l,
int r)
int mid = l +
((r - l)
>>1)
;return
mergesort
(arr, l, mid)
+mergesort
(arr, mid +
1, r)
+merge
(arr, l, mid, r);}
public
static
intmerge
(int
arr,
int l,
int m,
int r)
while
(p1 <= m)
while
(p2 <= r)
for(i =
0; i < help.length; i++
)return res;
}
歸併排序總結
歸併排序是利用分治思想,分開後一步一步歸併的過程。基本思路就是將陣列分成二組a,b,如果這二組組內的資料都是有序的,那麼就可以很方便的將這二組資料進行排序。可以將a,b組各自再分成二組。依次類推,當分出來的小組只有乙個資料時,可以認為這個小組組內已經達到了有序,然後再合併相鄰的二個小組就可以了。這樣...
歸併排序總結
歸併排序 merge sort 是建立在歸併操作上的一種有效的排序演算法,該演算法是採用分治法 divide and conquer 的乙個非常典型的應用。將已有序的子串行合併,得到完全有序的序列 即先使每個子串行有序,再使子串行段間有序。若將兩個有序表合併成乙個有序表,稱為二路歸併。過程描述 歸併...
歸併排序總結
看了關於歸併排序的這篇文章之後,寫個總結 歸併排序是採用分治法的典型案例。基本思路 將陣列分成兩組 a,b,如果a,b組內的資料是有序的,那麼很容易將兩組陣列進行排序。為了將a.b兩組資料有序,那麼將a,b再分成兩組。依次類推,當分出來的小組只有乙個資料時,可以認為小組組內已經達到了有序,然後再合併...