以數組{7,5,6,4}爲例,
1. 將數組中的每個元素看作是一個子數組,一邊將子數組排序(升序)後合併,一邊統計逆序對。
2. 對合並後的子數組重複第一步。
其中,統計逆序對的方法如下,:
總結,
時間複雜度爲O(n^logn),空間複雜度O(n)。
參考歸併排序的代碼可以得到如下代碼:
/*合併子數組,並統計逆序對的個數*/
int merge(vector<int> &data, int lo, int mi, int hi, int num)
{
int i = mi,//低位子數組的最大下標
j = hi,//高位子數組的最大下標
k = hi - lo;//輔助數組下標的最大值
vector<int> temp;
temp.resize(hi - lo + 1);//輔助數組的長度
while(i >= lo && j >= mi + 1)
{
if(data[i] > data[j])//若存在逆序對
{
num += j - mi;//逆序對的個數
temp[k--] = data[i--];
}
else//若不存在逆序對
{
temp[k--] = data[j--];
}
}
while(i >= lo)//當高位子數組元素已經全部複製到輔助數組中時,將低位子數組剩下的元素複製到輔助數組中
temp[k--] = data[i--];
while(j >= mi + 1)//當低子數組元素已經全部複製到輔助數組中,將高位子數組剩下的元素複製到輔助數組中
temp[k--] = data[j--];
for(i = lo, k = 0; i <= hi; i++, k++)//用輔助數組中的元素更新原數組中的元素
data[i] = temp[k];
return num;//返回逆序對的個數
}
/*主程序*/
int InversePairs(vector<int> data)
{
int n = data.size();//數組長度
if(data.empty())//若輸入空數組,返回0
return 0;
int size = 1;//第一次合併時,將每個元素看作一個子數組
int lo, mi, hi;//指示下標
int num = 0;//逆序對的個數
while(size < n)//子數組的長度小於原數組長度時,循環統計逆序對的個數
{
lo = 0;//從下標爲0的元素開始
while(lo + size < n)
{
mi = lo + size - 1;
hi = mi + size;
if(hi > n - 1)//若數組元素爲奇數個
hi = n - 1;
num = merge(data, lo, mi, hi, num);//合併子數組
lo = hi + 1;//下次合併開始元素的下標
}
size = size >> 1;//子數組長度擴大2倍
}
return num;//返回逆序對的個數
}