剑指 Offer 51. 数组中的逆序对

使用并归排序,类似于小合问题,不过排序是从大到小排

//新建一个和片段长度相同的辅助数组
//在两段都不越界的情况下左右指针大小进行比较,取左右两边较大的一个并拷贝进新数组
//由于左右两段在之前已经分别进行从大到小的排序,故当左部分的数进入新数组时,必定大于右部分指针之后所有的数,逆序对增加计数
//当左右两边指针数字相同时加入右边的,不会产生逆序数计数
//当有一个越界时,把不越界的剩余元素添加到新数组
//新数组覆盖排序的数组,完成范围内的从大到小排列

class Solution {
    public int reversePairs(int[] nums) {
        return mergeSort(nums,0,nums.length-1);
    }
    public int mergeSort(int[] nums,int L,int R){
        if(L>=R){
            return 0;
        }
        int mid=L+((R-L)>>1);//位运算算中值
        return mergeSort(nums,L,mid)+
        mergeSort(nums,mid+1,R)+merge(nums,L,mid,R);
    }

    public  static int merge(int []arr,int L,int M, int R ){
        int []help=new int[R-L+1];
        int i=0;
        int p1=L;//左指针
        int p2=M+1;//右指针
        int sum=0;
        while(p1<=M && p2<=R){
            sum+=arr[p1]>arr[p2]?R-p2+1:0;//dang左边的数大于右边时,加上右指针比之小的个数
            help[i++]=arr[p1]>arr[p2]?arr[p1++]:arr[p2++];//这里是总体的左大右小排序
        }
        while(p1<=M){//一边越界之后,将剩余元素加入到临时数组中,以下两个while只会进入一个
            help[i++]=arr[p1++];
        }
         while(p2<=R){
            help[i++]=arr[p2++];
        }
          for (int j = 0; j < help.length; j++) {
            arr[L+j] = help[j];//将有序的覆盖原有的
        }
        return sum;
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值