数组中的逆序对

这篇博客详细解析了一种通过分治法实现的计算数组中逆序对总数的方法。代码实现了一个名为`reversePairs`的函数,通过递归和归并排序的思想,有效地统计了逆序对。在归并过程中,通过`countReverse`函数精确计数交叉部分的逆序对。整个算法保证了效率和准确性。
摘要由CSDN通过智能技术生成

题目:
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。

例子:
在这里插入图片描述
代码1(分治法):

class Solution {

    public int reversePairs(int[] nums) {
        int len = nums.length;
        //数组长度太小,直接返回0
        if (len < 2){
            return 0;
        }
        //初始化copy数组并拷贝nums数组得值,目的是为了不损坏源数组。
        int[] copy = new int[len];
        for (int i = 0; i <= len - 1; i++){
            copy[i] = nums[i];
        }
        //定义一个辅助数组。
        int[] temp = new int[len];
        int totalCount = reverse(copy, 0, len - 1, temp);
        return totalCount;
    }

    private int reverse(int[] copy, int left, int right, int[] temp) {
        if (right <= left){
            return 0;
        }
        //下取整,可能遇到溢出问题,注意,这里是+号 int mid = (right + left) / 2,所以换了另一种方法。

        //错误的示例,注意跟下面的区别:int mid = (left + (right - left)) / 2;
        int mid = left + (right - left) / 2;
        //计算左边右边和交叉的逆序对并相加返回。
        int left_pair = reverse(copy, left, mid, temp);
        int right_pair = reverse(copy, mid + 1, right, temp);
        //如果两个子数组有序,那么直接返回。
        if (copy[mid] < copy[mid + 1]){
            return left_pair + right_pair;
        }
        int cross_pair = countReverse(copy, left, mid, right, temp);
        return left_pair + right_pair + cross_pair;


    }

    private int countReverse(int[] copy, int left, int mid, int right, int[] temp) {
        //之所以不new一个新数组,第一浪费空间,第二还要解决下标漂移的问题。
        for (int k = left; k <= right; k++){
            temp[k] =  copy[k];
        }
        //i,j分别指向两段有序数组的第一个元素,并开始比较。
        int i = left;
        int j = mid+1;
        int count = 0;
        for (int k = left; k <= right; k++){
            //做判断,看是否一边全部遍历完成。
            if (i == mid + 1){
                copy[k] = temp[j];
                j++;
            }else if (j == right + 1){
                copy[k] = temp[i];
                i++;
            } else if (temp[i] <= temp[j]){ //加上等号,可以避免归并排序的不稳定性。
                copy[k] = temp[i];
                i++;
            }else {
                copy[k] = temp[j];
                j++;
                count += (mid - i) + 1;
            }
        }
        return count;
    }
}

代码1详解:
其实就是一个递归,同时归并排序正好也是这样的形状,在归并排序的基础上加一个统计逆序数的就ok了。
在这里插入图片描述
这样图清晰的反映了怎么统计逆序数。
附上官方视频讲解:数组中的逆序数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值