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


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

解题思路

一刷2021/3/7
归并排序,但是大体思路还有点没理解的。

二刷2021/3/12
其实就是个在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。所以只要在归并模板中加一行代码即可。

注意temp的位置,不要定义在递归函数中,会超时
在这里插入图片描述
可以发现6如果是逆序,那么对于2来说,6之后的数字也大于它。所以逆序对就是mid-p1+1 也就是6-8的数字个数

代码

class Solution {
    //全局变量:统计逆序对数量
    private int count; 
    //临时数组,存放结果  一定要放在这,如果放在merge方法中,则每次递归都要创建一个数组,会超时!!
    int[] temp;
    public int reversePairs(int[] a) {
        count=0;
        temp=new int[a.length];
        MergeSort(a);
        return count;
    }
        private  void MergeSort(int[] a) {
        Sort(a, 0, a.length - 1);
    }
        //拆分
    private  void Sort(int[] a,int left,int right){
        if(left>=right){
            return;
        }
        int mid = left + (right - left) / 2;
        //二路归并要俩Sort
        Sort(a,left,mid);
        Sort(a,mid+1,right);
        merge(a,left,mid,right);
    }
    
    //合并
    private  void merge(int[] a, int left, int mid, int right) {
        int k=left;//存放指针
        //左右边界指针
        int p1=left;
        int p2=mid+1;
        while(p1<=mid&&p2<=right){
            if(a[p1]<=a[p2]){
                temp[k++]=a[p1++];
            }else{
                /*左边大于右边:为逆序,当大于时,
                表示左区间i及i之后的数都将大于j指向的数,所以出现了mid+1-i个逆序对*/
                //增加的一行代码,用来统计逆序对个数
                count=count+(mid-p1+1);
                temp[k++]=a[p2++];
            }
        }
        //左右还有剩余的就直接拼接上
        while(p1<=mid){
            temp[k++]=a[p1++];
        }
        while(p2<=right){
            temp[k++]=a[p2++];
        }
        //存放回原数组
        for(int i=left;i<=right;i++){
            a[i]=temp[i];
        }
    }
    
}

文章作者: fFee-ops
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 fFee-ops !
评论
  目录