求陣列的逆序數

2021-06-21 07:50:54 字數 1427 閱讀 5960

題目:在乙個排列中,如果一對數的前後位置與大小順序相反,即前面的數大於後面的數,那麼它們就稱為乙個逆序。乙個排列中逆序的總數就稱為這個排列的逆序數。

現在,給你乙個n個元素的序列,請你判斷出它的逆序數是多少。

比如 1 3 2 的逆序數就是1。

方法1::o(n^2)這個就不說了。

方法2: 借助歸併排序達到o(nlgn)的時間複雜度,當然犧牲了一點空間。

這裡主要描述一下方法2,前提是你需要懂一點歸併排序的原理。舉個例子,我們對做歸併排序(公升序)。一步一步的歸併過程分解如下圖所示。

a                                4352

b                 43                            52

c        4                 3             5             2                 

d                 34                            25

e                                2345

如上圖所示,遞迴到第c行時,遞迴結束,開始回溯(歸併)。在歸併排序過程中,歸併是在merge函式中,對左半邊陣列和右半邊陣列做歸併。先看第c行最左邊的4和3,在歸併的時候會判斷這兩個數的大小,4>3,所以這趟歸併完結果為34。顯然,我們在歸併這裡做比較的時候可以記錄下來前半邊陣列比後半邊陣列大的對數。再看第d行,這裡左半邊陣列是34,右半邊是25,都已經有序了。按照歸併排序,我們先要比較3和2的大小,然後比較3和5,再比較4和5。只有3是大於2的,但是這表明這次遞迴逆序對只有1個嗎?實際不是的,3已經大於2了,已知左半邊陣列是公升序的,那麼左半邊陣列3之後的元素都是大於2的(4也大於2),而這個逆序的對數非常容易求出。

形成**,發現實際上只是在歸併排序的基礎上加了乙個全域性變數和一行**。

#include using namespace std;

int sum = 0;

void merge(int a, int low, int mid, int high)

} while (i<=mid)

temp[k++] = a[i++];

while (j<=high)

temp[k++] = a[j++];

for (i=low,k=0; i<=high; i++)

free(temp);

temp = null;

}void mergesort(int a, int low, int high)

}int main()

; mergesort(a, 0, 3);

cout << sum << endl;

return 0;

}

還有用樹狀陣列的方法,不是很熟悉這個結構,就不寫了。。

分治演算法 求陣列逆序數

題目 在陣列中的兩個數字如果前面乙個數字大於後面乙個數字 則這兩個數字組成乙個逆序對 輸入乙個陣列 求這個陣列中逆序對的個數 先把陣列分割成子陣列 先統計出子陣列內部的逆序對的數目 然後再統計出兩個相鄰子陣列之間的逆序對的數目 統計逆序對的過程中 還需要對陣列進行排序 這類似與歸併排序 演算法的時間...

求數列的逆序數

在乙個排列中,如果一對數的前後位置與大小順序相反,即前面的數大於後面的數,那麼它們就稱為乙個逆序。乙個排列中逆序的總數就稱為這個排列的逆序數。123 4567 891011 1213 1415 1617 1819 2021 2223 2425 2627 28ll a 500005 tem 50000...

求陣列逆序對數

題目 對於乙個元素個數為n的陣列a,若 a i a j 且0 i j n,則a i 和a j 為乙個逆序對。現在要求給定陣列的逆序對數 解析 對於這乙個題目,最容易想到的方法即順序掃瞄整個陣列。沒掃瞄到乙個元素,則將該元素與其後面的所有元素進行比較,若後面的元素比該元素大,則找到乙個逆序數。這一過程...