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

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


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值