微软100题-求数组中的逆序对

来源:互联网 发布:局域网签到软件 编辑:程序博客网 时间:2024/05/23 19:11

求数组中的逆序对的个数:在数组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