演算法練習 逆序對

2021-10-04 16:43:01 字數 2059 閱讀 9394

逆序對問題算是很經典了,最簡單的暴力破解時間複雜度o(n2),時間複雜度大於o(n2)的演算法是非常糟糕了,所以我們採用歸併排序的演算法改動一下,即可獲得o(nlogn)的演算法。

逆序對定義:數列中如果 i < j && arr[i] > arr[j],則arr[i]和arr[j]為一對逆序對。

// 逆序對個數

private

static

long ropcount =0;

/** * 計算逆序對

* * @param arr

* @param left

* @param right

*/public

static

void

calcrop

(int

arr,

int left,

int right)

/** * 一次計算

* * @param arr

* @param left

* @param mid

* @param right

*/public

static

void

calc

(int

arr,

int left,

int mid,

int right)

}

正確性測試有那麼幾組資料

資料逆序對的數量

2032331

000分別跑起來,結果都對的上,暫未發現結果不符的資料。

壓力測試

跑一百萬條資料,看看用時。

int

arr =

newint

[1000

*1000];

for(

int i =

0; i < arr.length; i++

)long start = system.

currenttimemillis()

;calcrop

(arr,

0, arr.length -1)

;system.out.

println

(ropcount)

;long end = system.

currenttimemillis()

;system.out.

println

("一百萬條資料用時:"

+(end-start)

/1000

+"s"

);

害!可能是我自己寫的一次歸併演算法不好,一百萬條資料竟然要用一分鐘。。。

我又改了改,上面那個一次歸併的演算法使用時間換空間,一直是在arr中操作,需要不斷的搬動元素,所以耗時巨大。

改進的思路是空間換時間,使用乙個輔助陣列和原陣列相同,使用大小個入隊的方法來進行一次歸併。

改進後的一次歸併計算的方法如下:

/**

* 一次計算

* * @param arr

* @param left

* @param mid

* @param right

*/public

static

void

calc

(int

arr,

int left,

int mid,

int right)

else

}// 後半部分沒搬完

if(i > mid && j <= right)

// 前半部分沒搬完

if(i <= mid && j > right)

system.

arraycopy

(helper,

0, arr, left, helper.length)

;}

再用百萬條資料測試一下:

看吧,速度有了質的提公升,所以在硬體發達的時代,不要吝嗇而用時間換空間,適當的使用輔助空間會使演算法速度大幅度提公升。

就是這樣哈哈,拜了個拜!

普及練習場 分治演算法 逆序對

題目鏈結 看到這個資料量,你就不應該想著去寫個暴力。我原來已經寫過一遍這個題目了,並且還記得是歸併排序來做,但是有點記不得是怎麼推導出思路的了,因此決定重新推導一遍。我找到了原來的ppt,並且加一點自己的理解吧。一開始的時候應該是1 2 但是1 被分解成更小的1 和更小的2 當只有兩個數的時候,就只...

演算法之逆序對

假設a 1.n 是乙個有n個不同數的陣列。若ia j 則對偶 i,j 稱為a的乙個逆序對 inversion 列出陣列的5個逆序對 由集合中的元素構成的什麼陣列具有最多的逆序對?它有多少逆序對?插入排序的執行時間與輸入陣列中的逆序對的數量有什麼關係?給出乙個求在n個元素的任何排列中逆序對數量的演算法...

演算法篇 逆序對

設 a 為乙個有 n 個數字的有序集 n 1 其中所有數字各不相同。如果存在正整數 i,j使得 1 i j n 而且 a i a j 則 這個有序對稱為 a 的乙個逆序對,也稱作逆序數。排序的過程就是消除逆序對的過程。逆序對越多,相對來說排序所需要的時間就越多。列舉陣列元素的所有組合,對於 長度為 ...