日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java中mergesort函数怎么用,由mergeSort引发的一些思考

發布時間:2023/12/31 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java中mergesort函数怎么用,由mergeSort引发的一些思考 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

重新梳理一下歸并排序以及一些相關的東西。

對于歸并排序大家如果需要回憶下是個什么東西的話,可以點擊這個鏈接,里面有各種排序的動畫演示以及講解,比我再用文字贅述一遍要好得多,功能相當強大。

先給出歸并排序的js代碼實現:

function mergeSort(arr, l, r) {

if (l === r) {

return;

}

let mid = Math.floor((r + l) / 2);

mergeSort(arr, l, mid);

mergeSort(arr, mid + 1, r);

merge(arr, l, mid, r);

}

function merge(arr, l, mid, r) {

let leftIndex = l;

let rightIndex = mid + 1;

let helpArr = [];

while(leftIndex <= mid && rightIndex <= r) {

let leftItem = arr[leftIndex];

let rightItem = arr[rightIndex];

if (leftItem < rightItem) {

helpArr.push(leftItem);

leftIndex++;

} else {

helpArr.push(rightItem);

rightIndex++;

}

}

// 這倆循環只會進去一個,因為經過上面的比較,要么左邊部分走完了,要么右邊部分走完了

while(leftIndex <= mid) {

helpArr.push(arr[leftIndex]);

leftIndex++;

}

while(rightIndex <= r) {

helpArr.push(arr[rightIndex]);

rightIndex++;

}

for (let index = 0; index < helpArr.length; index++) {

arr[l] = helpArr[index];

l++;

}

}

如何估計歸并排序的時間復雜度呢?

由于上面采用了遞歸寫法,我們使用master公式對遞歸進行時間復雜度估算,以下是公式詳情。

T(n) = a*T(n/b) + O(n^d)

(1)、log(b, a) > d => 復雜度為O(n^log(b, a))

(2)、log(b, a) = d => 復雜度為O(n^d*logn)

(3)、log(b, a) < d => 復雜度為O(n^d)

a代表遞歸的次數,由于在mergeSort中調用了兩次mergeSort,所以歸并排序中a = 2。

b代表樣本量被劃分幾份,由于我們對樣本量是一分為二將數組分為left和right部分,所以歸并排序中b = 2。

O(n^d)代表其他操作的時間復雜度,所以在歸并排序中主要是merge這個函數,相當于是執行了一次數組遍歷,則為O(n)。

a = 2,b = 2,d = 1根據master公式,復雜度為nlogn。

我們知道冒泡排序、選擇排序、插入排序的時間復雜度都是O(n^2),當樣本量比較大的時候,n^2比之nlogn差了可不是一星半點。這是為什么呢?因為在其他三種排序中,會浪費元素之間的比較,比如冒泡排序冒泡比較一輪只定位了一個元素,下一輪冒泡又只定位一個元素,會浪費元素之間的相互比較;而歸并排序通過分治,由小到大進行比較合并的過程中,上一次比較合并的元素不會再次發生比較,有序的區域成規模增長,這樣就不會浪費比較,節省了時間。

由歸并排序引入數組小和問題和數組逆序對問題。

根據小和的題目要求,我們思考一下可以發現,在歸并排序過程中,left和right部分進行比較合并的時候,其實就可以找到左邊部分比右邊部分小的數,意思就是說我們可以很方便的在merge這個函數執行過程中來計算數組的小和且會快很多,因為合并的時候左右兩遍都是有序的,如果一個數比右邊的第一個數字小,我們可以得知這個數字肯定比右邊全部的數字都小。

舉個例子,比如left = [1,2,3],right = [4,5,6],1小于4,說明右邊三個數都比1大,假如說小和等于sum,那么sum就要加1 * 3。

代碼實現一下小和:

function smallSum(arr) {

if (!arr || arr.length < 2) {

return 0;

}

return mergeSort(arr, 0, arr.length - 1);

}

function mergeSort(arr, l, r) {

if (l === r) {

return 0;

}

let mid = Math.floor((l + r)/2);

return mergeSort(arr, l, mid)

+ mergeSort(arr, mid + 1, r)

+ merge(arr, l, mid, r)

}

function merge(arr, l, mid, r) {

let leftIndex = l;

let rightIndex = mid + 1;

let helpArr = [];

let sum = 0;

while(leftIndex <= mid && rightIndex <= r) {

let leftItem = arr[leftIndex];

let rightItem = arr[rightIndex];

if (leftItem < rightItem) {

/**相對于歸并排序增加的部分**/

let tempSum = (r - rightIndex + 1) * leftItem

sum += tempSum;

/***************************/

helpArr.push(leftItem);

leftIndex++;

} else {

helpArr.push(rightItem);

rightIndex++;

}

}

/**這部分和歸并排序merge函數一樣**/

return sum;

}

對于小和都知道如何使用歸并排序進行求解之后,逆序對其實和小和是一樣的,只是反過來了而已,以下直接貼出代碼。

function inversePairs(arr) {

if (!arr || arr.length < 2) {

return [];

}

return mergeSort(arr, 0, arr.length - 1);

}

function mergeSort(arr, l, r) {

if (l === r) {

return [];

}

let mid = Math.floor((l + r)/2);

return [

...mergeSort(arr, l, mid),

...mergeSort(arr, mid + 1, r),

...merge(arr, l, mid, r)

];

}

function merge(arr, l, mid, r) {

let leftIndex = l;

let rightIndex = mid + 1;

let helpArr = [];

let res = [];

while(leftIndex <= mid && rightIndex <= r) {

let leftItem = arr[leftIndex];

let rightItem = arr[rightIndex];

if (leftItem < rightItem) {

helpArr.push(leftItem);

leftIndex++;

} else {

/**相對于歸并排序增加的部分**/

res.push([leftItem, rightItem]);

/***************************/

helpArr.push(rightItem);

rightIndex++;

}

}

/**這部分和歸并排序merge函數一樣**/

return res;

}

以上是對歸并排序這部分內容進行的一些回顧和總結,希望能加深自己對它的理解,能在其他更多的地方將其運用上;如果有不正確的地方,大家可以踴躍指出,我將及時改正。

總結

以上是生活随笔為你收集整理的java中mergesort函数怎么用,由mergeSort引发的一些思考的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。