求數組中的逆序對的個數:在數組a中如果a[i]>a[j].且i<j則<i,j>稱爲一個逆序數對,例如數組是7,5 ,6 ,4 則逆序對共有 7,5 7,6 7,4 5,4 6,4 五個逆序對,剛開始的時候沒有思路,看了看解答之後發現,還是採用分治的思想,類似於用歸併算法實現,
空間複雜度爲n,需要一個額外的數組來存儲,時間複雜度爲log2n(2是下標了,懶得打公式了)。具體的圖解可看一下何海濤裏面的圖示。
記錄一下我的代碼吧,
//這個程序是求數組中的逆序對的
//劍指offer一書中的36題
#include<iostream>
using namespace std;
int b[100];
int n;
int Countreversion(int a[], int begin, int end)
{
if(end == (begin+1))
{
if( a[begin] > a[end])
{
int t=a[begin];
a[begin] = a[end];
a[end] = t;
return 1;
}
else
{
return 0;
}
}
else if( begin ==end)
return 0;
else if( end>(begin+1))
{
int mid = (begin+end)/2;
int left = Countreversion (a,begin,mid); cout << "begin is " <<begin << " mid is "<< mid <<endl;cout << "left is" << left<<endl;
cout << "The elment in a is : ";
for(int k=0; k<n; k++)
cout<<a[k]<<" ";
cout <<endl;
int right = Countreversion (a, mid+1, end); cout << " mid+1 is " <<mid+1 <<" end is " <<end <<endl;cout << " right is " <<right <<endl;
cout << "The elment in a is : ";
for(int k=0; k<n; k++)
cout <<a[k]<<" ";
cout <<endl;
int p=mid, q=end;
int current =end;
int number =left+right;
int next_q=end; //next_q 求的是下一次判斷時q的起始位置,比如 左邊是6,7,右邊是 5,9 ,則下次從5開始,因爲7<9了,
while(p >=begin)
{
q = next_q;
while( q>=(mid+1) && a[p] <=a[q])
{
b[current--] = a[q];
q--;
}
if( q>=(mid+1) && a[p]>a[q])
{
next_q = q;
b[current--] = a[p];
number+= q-(mid+1)+1;
p--;
}
else if( q<(mid+1))
{
while( p>=begin)
{
b[current--]=a[p];
p--;
}
}
if(p<begin && q>=(mid+1))// 這部分要注意,是處理左數組已經全部都複製到臨時數組裏了,但是右數組還有剩餘
{//最簡單的情況比如 左數組 6 ,7 右數組 3,4
//臨時數組裏會是6,7,6,7 ,也就是右數組還沒放到臨時數組中,則放進去爲3,4,6,7
//之前程序出錯,前面的都對,唯獨忘記處理這種情況了。
while(q>=(mid+1))
{
b[current--] = a[q];
q--;
}
}
}
for(int i=begin ; i<=end; i++)
a[i]=b[i];
return number;
}
}
int main()
{
int a[100];
cin >>n;
for(int i=0; i<n; i++)
{
cin >>a[i];
b[i]=a[i];
}
for(int k=0; k<n; k++)
cout << " a is " <<a[k]<<" ";
cout <<endl;
cout << "The final result is " << Countreversion(a,0,n-1)<<endl;
return 1;
}
提供幾組測試數據:
n=7 a: 6 7 4 3 5 1 2 結果爲17
n=7 a:1 2 3 4 5 6 7 結果爲0
n=7 a:7 6 5 4 3 2 1 結果爲21